base64Captcha
A flexible Go library for generating digit, string, math, Chinese-character, and audio CAPTCHAs encoded as base64 strings.
Repository Health
Technical Analysis
base64Captcha is a Go library that generates CAPTCHA challenges and returns them as ready-to-embed base64-encoded image or audio strings, so a backend can hand a frontend a data URI directly without touching the filesystem. It ships five built-in captcha types out of the box — digit, alphanumeric string, arithmetic math, Chinese-character, and spoken-digit audio — each implemented as its own driver with configurable dimensions, noise, skew, and font options.
The library is built around two small interfaces, Driver and Store, that separate “how the challenge is generated and rendered” from “where the answer is kept for verification.” A Captcha struct composes one of each, so swapping in a Redis- or etcd-backed store, or a custom driver for a new captcha style, requires no changes to calling code. A thread-safe in-memory store with periodic expiration-based garbage collection is included by default, plus a sync.Map-based alternative.
It’s aimed at Go web services (net/http, Gin, Echo, etc.) that need self-hosted, dependency-light bot mitigation for login, registration, or form-submission endpoints without calling out to a third-party CAPTCHA API.
What You Get
- Five built-in captcha drivers: digit, alphanumeric string, arithmetic math, Chinese-character, and spoken-digit audio
- A
Driver/Storeinterface pair that lets you plug in custom challenge rendering or custom answer storage (Redis, etcd, sync.Map, etc.) - A default in-memory
Storeimplementation with mutex-protected access and automatic expiration-based garbage collection - Configurable image dimensions, noise/dot count, skew, background color, embedded and custom TrueType fonts, and decorative line styles
- Direct base64 string output for both PNG images and WAV audio, with no temp files or external service calls required
Common Use Cases
- Protecting login and registration forms on a Go backend from automated bot submissions
- Adding a human-verification step to public contact forms or comment submission endpoints
- Serving accessible audio CAPTCHAs alongside image CAPTCHAs for visually impaired users
- Generating localized CAPTCHAs (Chinese-character driver) for region-specific applications
- Self-hosted CAPTCHA generation for services that can’t depend on third-party APIs like reCAPTCHA
Under The Hood
Architecture
The library centers on a small Captcha struct (captcha.go) composed of a Driver and a Store, following a strategy pattern: Generate() asks the driver for an id/question/answer triple via GenerateIdQuestionAnswer(), renders it via DrawCaptcha() into an Item, persists the answer through Store.Set(), and returns the item’s base64-encoded string; Verify() reverses the lookup through Store.Get()/Store.Verify(). Each of the five captcha types (driver_digit.go, driver_string.go, driver_math.go, driver_chinese.go, driver_audio.go) implements the two-method Driver interface independently, and each pairs with its own Item* renderer (item_digit.go, item_char.go, item_audio.go) that owns the actual image/audio drawing logic — so adding a new captcha style means implementing one driver and one item type without touching the core Captcha struct. Storage is decoupled the same way: store_memory.go and store_sync_map.go both satisfy the three-method Store interface, and either can be swapped in without changing driver code.
Tech Stack
Written in Go 1.16+ with a deliberately minimal dependency footprint: github.com/golang/freetype (and its truetype subpackage) for font rasterization, and golang.org/x/image for font/image primitives, plus the standard library’s image, image/png, image/draw, encoding/base64, sync, and container/list packages. Fonts are embedded directly into the binary via fonts_embedded.go / fonts_embedded_default.go (Go’s embed mechanics), and audio samples are baked into sounds.go as a large generated data file. No database, ORM, or network client is required — everything needed to render a captcha ships inside the module itself.
Code Quality
The project has table-driven unit tests alongside nearly every source file (driver_digit_test.go, driver_math_test.go, item_char_test.go, store_memory_test.go, etc.), giving each driver, item renderer, and store implementation direct test coverage, and a GitHub Actions workflow (“Test”) runs them on push. Error handling is explicit where it matters — DrawCaptcha and Store.Set return error values that callers check — though some older call sites (the store’s Verify return value) rely on plain boolean comparison rather than richer error types. Naming is consistent and Go-idiomatic (NewDriverXxx, NewItemXxx constructors, exported Default* package-level instances), and doc comments precede exported types and functions, though the package predates Go modules’ stricter conventions in a few spots (mixed indentation in captcha.go, a legacy main.go.md docs file rather than a runnable example).
What Makes It Unique
Most Go captcha packages support a single challenge type; base64Captcha instead standardizes on a common Driver/Store abstraction and ships five ready-made challenge types (including a Chinese-character driver and a spoken-audio driver) behind it, so a project can offer image and audio CAPTCHAs, or swap in a custom localized character set, through the same integration code. Returning results as base64 strings directly — rather than writing image files to disk or requiring a static file server — keeps the library stateless and easy to drop into a JSON API handler.
Used by 2 apps in this directory
BillionMail
Marketing
Self-hosted email server and marketing platform that gives you unlimited sending, full deliverability control, and AI-assisted campaigns without monthly fees.
Nightingale
Monitoring
Open-source alerting engine that connects to any time-series or log data source and routes alarms to 20+ notification channels with AI-assisted triage.