How to Build a Custom CAPTCHA Service with Python Sanic

This tutorial shows how to generate a simple image‑based CAPTCHA using Python's Pillow library and the Sanic web framework, store the code in a session, and validate user input, with notes on adding asynchronous refresh functionality.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
How to Build a Custom CAPTCHA Service with Python Sanic

Dependencies required: sanic==19.9.0 and Pillow==7.0.0.

Verification code generation

import random
import string
import uuid
import base64
import platform
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
from sanic import Sanic
from sanic.response import HTTPResponse, text
from sanic.views import HTTPMethodView

app = Sanic()
session = {}

class VerifyCode:
    def __init__(self, numbers: int):
        """Specify the number of characters to generate"""
        self.number = numbers

    def draw_lines(self, draw, num, width, height):
        """Draw interference lines"""
        x1 = random.randint(0, width / 2)
        y1 = random.randint(0, height / 2)
        x2 = random.randint(0, width)
        y2 = random.randint(height / 2, height)
        draw.line(((x1, y1), (x2, y2)), fill='black', width=1)

    def random_color(self):
        """Random color"""
        return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))

    def gene_text(self):
        """Generate random verification text"""
        return "".join(random.sample(string.ascii_letters + string.digits, self.number))

    def get_verify_code(self):
        """Create image and code"""
        code = self.gene_text()
        width, height = 130, 30
        im = Image.new("RGB", (width, height), "white")
        sysstr = platform.system()
        font = None
        if sysstr == "Windows":
            font = ImageFont.truetype("C:\\WINDOWS\\Fonts\\STXINGKA.TTF", 25)
        elif sysstr == "Darwin":
            font = ImageFont.truetype("/Library/Fonts/AppleMyungjo.ttf", 25)
        draw = ImageDraw.Draw(im)
        for item in range(self.number):
            draw.text((5 + random.randint(-5,5) + 23*item,
                       5 + random.randint(-5,5)),
                      text=code[item],
                      fill=self.random_color(),
                      font=font)
            self.draw_lines(draw, self.number, width, height)
        return im, code

class SimpleView(HTTPMethodView):
    body = """<html>...template omitted for brevity...</html>"""

    async def get(self, request):
        return self.response(error="")

    async def post(self, request):
        uuid = request.cookies.get("uuid", "1")
        verfy_code = request.form.get("code", "2").lower()
        code = session.get(uuid, "").lower()
        if code == verfy_code:
            return text('验证码正确')
        return self.response(error='<input placeholder="验证码错误" disabled>')

    def response(self, error):
        im, code = VerifyCode(5).get_verify_code()
        buf = BytesIO()
        im.save(buf, "jpeg")
        base64_data = base64.b64encode(buf.getvalue()).decode()
        id = uuid.uuid1().__str__()
        session[id] = code
        body = self.body.format(base64_data=base64_data, error=error)
        response = HTTPResponse(body, content_type="text/html; charset=utf-8")
        response.cookies["uuid"] = id
        return response

app.add_route(SimpleView.as_view(), '/code')

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

The implementation creates a simple CAPTCHA image, stores the generated code in a session dictionary, and validates user input; a refresh mechanism can be added by exposing an asynchronous endpoint that regenerates the image and updates the session key.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PythonCaptchaWeb Developmentverificationsanic
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.