A powerful captcha verification package for discord.py bots.
Project description
Discord.py Captcha
A powerful package for discord.py v2 that allows you to easily create CAPTCHAs for Discord Servers.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:
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
- 🎮 Need help or want to chat? Join our Discord Server!
- 🐛 Found a bug? Open an issue on our GitHub repository.
- 💡 Have a feature request? Submit it here!
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
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 discord_py_captcha-1.0.2.tar.gz.
File metadata
- Download URL: discord_py_captcha-1.0.2.tar.gz
- Upload date:
- Size: 248.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
95c6156af8c0e4d0ab3066dbc568fa6eedbb28934f7c0664e1d55b1af451041d
|
|
| MD5 |
d48f335c5ee1ce1f9440c3a1fac3f885
|
|
| BLAKE2b-256 |
e758fa0e5fff1d7d8d8c00abe592363ec2e49c7d1bca368d2c85ac65edc38b12
|
File details
Details for the file discord_py_captcha-1.0.2-py3-none-any.whl.
File metadata
- Download URL: discord_py_captcha-1.0.2-py3-none-any.whl
- Upload date:
- Size: 14.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fe5bc74a21752219500bd06aa700615913eb61be84e34569761e210504c40cd4
|
|
| MD5 |
3184b04876748df87001d42f89c72764
|
|
| BLAKE2b-256 |
0474a42403eeb62358454224a6193d8ba7dc341d41e68ad991d68598f4f1cff0
|