Go captcha
🖖 GoCaptcha: A high-performance, interactive behavior captcha library for Go. Supporting click, slide, drag-drop, and rotation modes to secure your applications with ease.
GoCaptcha is a powerful, modular, and highly customizable behavioral CAPTCHA library that supports multiple interactive CAPTCHA types: Click, Slide, Drag-Drop, and Rotate. The project is written primarily in Go, distributed under the Apache License 2.0 license, first published in 2021. It has gained significant community traction with 2,331 stars and 215 forks on GitHub. Key topics include: base64, base64-captcha, behavior-analysis, captcha, captcha-generator.
<p style="text-align: center"><a href="https://github.com/wenlng/go-captcha">GoCaptcha</a> is a powerful, modular, and highly customizable behavioral CAPTCHA library that supports multiple interactive CAPTCHA types: Click, Slide, Drag-Drop, and Rotate.</p> <p style="text-align: center"> ⭐️ If it helps you, please give a star.</p> <div align="center"> <img src="https://github.com/wenlng/git-assets/blob/master/go-captcha/go-captcha-v2.jpg?raw=true" alt="Poster"> </div> <br/> <hr/> <br/>English | 中文
Ecosystem
| Project | Desc |
|---|---|
| document | GoCaptcha Documentation |
| online demo | GoCaptcha Online Demo |
| go-captcha-example | Golang + Web + APP Example |
| go-captcha-assets | Embedded Resource Assets for Golang |
| go-captcha | Golang CAPTCHA Library |
| go-captcha-jslib | JavaScript CAPTCHA Library |
| go-captcha-vue | Vue CAPTCHA Library |
| go-captcha-react | React CAPTCHA Library |
| go-captcha-angular | Angular CAPTCHA Library |
| go-captcha-svelte | Svelte CAPTCHA Library |
| go-captcha-solid | Solid CAPTCHA Library |
| go-captcha-uni | UniApp CAPTCHA, compatible with Apps, Mini-Programs, and Fast Apps |
| go-captcha-service | GoCaptcha Service, supports binary and Docker image deployment, <br/>provides HTTP/gRPC interfaces,<br/> supports standalone and distributed modes (service discovery, load balancing, dynamic configuration) |
| go-captcha-service-sdk | GoCaptcha Service SDK Toolkit, includes HTTP/gRPC request interfaces,<br/> supports static mode, service discovery, and load balancing. |
| ... |
Core Features
- Diverse CAPTCHA Types: Supports Click, Slide, Rotate, and Drag behavioral CAPTCHAs, suitable for various interaction scenarios.
- Highly Customizable: Flexible configuration of images, fonts, colors, angles, sizes, etc., through Options and Resources.
- Advanced Image Processing: Built-in dynamic image generation and processing, supporting main images, thumbnails, puzzle pieces, and shadow effects.
- Modular Architecture: Clear code structure, adhering to Go best practices, making it easy to extend and maintain.
- High-Performance Design: Optimized resource management and image generation, suitable for high-concurrency scenarios.
- Cross-Platform Compatibility: Generated CAPTCHA images can be seamlessly integrated into web applications, mobile apps, or other systems requiring CAPTCHAs.
CAPTCHA Types
go-captcha supports the following four CAPTCHA types, each with unique interaction methods, generation logic, and application scenarios:
- Click CAPTCHA: Users click specified points or characters on the main image, supporting text and graphic modes.
- Slide CAPTCHA: Users slide a puzzle piece to the correct position on the main image, supporting basic and drag-drop modes.
- Drag-Drop CAPTCHA: A variant of the Slide CAPTCHA, allowing users to drag-drop a puzzle piece to a target position within a larger range.
- Rotate CAPTCHA: Users rotate a thumbnail to align with the main image’s angle.
Install
shell$ go get -u github.com/wenlng/go-captcha/v2@latest
Import Module
<br />gopackage main // Import modules on demand import "github.com/wenlng/go-captcha/v2/${click|slide|rotate}" func main(){ // ... }
🖖 Click CAPTCHA
The Click CAPTCHA requires users to click specified points or characters on the main image, ideal for quick verification scenarios. It supports two modes:
- Text Mode:Displays characters (e.g., letters, numbers, or Chinese characters), and users click the corresponding characters.
- Graphic Mode:Displays graphics (e.g., icons or shapes), and users click the corresponding graphics.
How It Works
- Generate Main Image (
masterImage): Contains randomly distributed points or characters, typically in JPEG format. - Generate Thumbnail (
thumbImage): Displays the target points or characters to be clicked, typically in PNG format. - User Interaction: Users click coordinates on the main image, and the frontend captures and sends the coordinates to the backend.
- Verification Logic: The backend compares the clicked coordinates with the target points (
dots) to verify a match.
Code Example
gopackage main import ( "encoding/json" "fmt" "image" "log" "io/ioutil" "github.com/golang/freetype" "github.com/golang/freetype/truetype" "github.com/wenlng/go-captcha/v2/base/option" "github.com/wenlng/go-captcha/v2/click" "github.com/wenlng/go-captcha/v2/base/codec" ) var textCapt click.Captcha func init() { builder := click.NewBuilder( click.WithRangeLen(option.RangeVal{Min: 4, Max: 6}), click.WithRangeVerifyLen(option.RangeVal{Min: 2, Max: 4}), ) // You can use preset material resources:https://github.com/wenlng/go-captcha-assets fontN, err := loadFont("../resources/fzshengsksjw_cu.ttf") if err != nil { log.Fatalln(err) } bgImage, err := loadPng("../resources/bg.png") if err != nil { log.Fatalln(err) } builder.SetResources( click.WithChars([]string{ "1A", "5E", "3d", "0p", "78", "DL", "CB", "9M", // ... }), click.WithFonts([]*truetype.Font{ fontN, }), click.WithBackgrounds([]image.Image{ bgImage, }), ) textCapt= builder.Make() } func loadPng(p string) (image.Image, error) { imgBytes, err := ioutil.ReadFile(p) if err != nil { return nil, err } return codec.DecodeByteToPng(imgBytes) } func loadFont(p string) (*truetype.Font, error) { fontBytes, err := ioutil.ReadFile(p) if err != nil { panic(err) } return freetype.ParseFont(fontBytes) } func main() { captData, err := textCapt.Generate() if err != nil { log.Fatalln(err) } dotData := captData.GetData() if dotData == nil { log.Fatalln(">>>>> generate err") } dots, _ := json.Marshal(dotData) fmt.Println(">>>>> ", string(dots)) var mBase64, tBase64 string mBase64, err = captData.GetMasterImage().ToBase64() if err != nil { fmt.Println(err) } tBase64, err = captData.GetThumbImage().ToBase64() if err != nil { fmt.Println(err) } fmt.Println(">>>>> ", mBase64) fmt.Println(">>>>> ", tBase64) //err = captData.GetMasterImage().SaveToFile("../resources/master.jpg", option.QualityNone) //if err != nil { // fmt.Println(err) //} //err = captData.GetThumbImage().SaveToFile("../resources/thumb.png") //if err != nil { // fmt.Println(err) //} }
Make Instance
- builder.Make()
- builder.MakeShape()
Configuration Options
click.NewBuilder(click.WithXxx(), ...) OR builder.SetOptions(click.WithXxx(), ...)
| Options | Desc |
|---|---|
| Main Image | |
| click.WithImageSize(option.Size) | Set main image size, default 300x220 |
| click.WithRangeLen(option.RangeVal) | Set range for random content length |
| click.WithRangeAnglePos([]option.RangeVal) | Set range for random angles |
| click.WithRangeSize(option.RangeVal) | Set range for random content size |
| click.WithRangeColors([]string) | Set random colors |
| click.WithDisplayShadow(bool) | Enable/disable shadow display |
| click.WithShadowColor(string) | Set shadow color |
| click.WithShadowPoint(option.Point) | Set shadow offset position |
| click.WithImageAlpha(float32) | Set main image transparency |
| click.WithUseShapeOriginalColor(bool) | Use original graphic color (valid for graphic mode) |
| Thumbnail | |
| click.WithThumbImageSize(option.Size) | Set thumbnail size, default 150x40 |
| click.WithRangeVerifyLen(option.RangeVal) | Set range for random verification content length |
| click.WithDisabledRangeVerifyLen(bool) | Disable random verification length, matches main content |
| click.WithRangeThumbSize(option.RangeVal) | Set range for random thumbnail content size |
| click.WithRangeThumbColors([]string) | Set range for random thumbnail colors |
| click.WithRangeThumbBgColors([]string) | Set range for random thumbnail background colors |
| click.WithIsThumbNonDeformAbility(bool) | Prevent thumbnail content deformation |
| click.WithThumbBgDistort(int) | Set thumbnail background distortion (option.DistortLevel1 to option.DistortLevel5) |
| click.WithThumbBgCirclesNum(int) | Set number of small circles in thumbnail background |
| click.WithThumbBgSlimLineNum(int) | Set number of lines in thumbnail background |
Set Resources
builder.SetResources(click.WithXxx(), ...)
| Options | Desc |
|---|---|
| click.WithChars([]string) | Set text seed |
| click.WithShapes(map[string]image.Image) | Set graphic seed |
| click.WithFonts([]*truetype.Font) | Set fonts |
| click.WithBackgrounds([]image.Image) | Set main image backgrounds |
| click.WithThumbBackgrounds([]image.Image) | Set thumbnail backgrounds |
Captcha Data
captData, err := capt.Generate()
| Method | Desc |
|---|---|
| GetData() map[int]*Dot | Get verification data |
| GetMasterImage() imagedata.JPEGImageData | Get main image |
| GetThumbImage() imagedata.PNGImageData | Get thumbnail |
Validate the captcha
ok := click.Validate(srcX, srcY, X, Y, width, height, paddingValue)
| Params | Desc |
|---|---|
| srcX | User X-axis |
| srcY | User Y-axis |
| X | X-axis |
| Y | Y-axis |
| width | Width |
| height | Height |
| paddingValue | Set the padding value |
Notes
- The character set (
chars) or graphic set (shapes) must be longer thanrangeLen.Max, otherwiseCharRangeLenErrorShapesRangeLenErrwill be triggered. - Graphic mode requires valid image resources (
shapeMaps), otherwiseShapesTypeErrwill be triggered. - Background images must not be empty, otherwise
EmptyBackgroundImageErrwill be triggered.
🖖 Slide Or Drag-Drop CAPTCHA
The Slide CAPTCHA requires users to slide a puzzle piece to the correct position on the main image. It supports two modes:
- Basic Mode: The puzzle piece slides along a fixed Y-axis, suitable for simple verification scenarios.
- Drag-Drop Mode: The puzzle piece can be freely dragged within a larger range, suitable for scenarios requiring higher interaction freedom.
How It Works
- Generate Main Image (
masterImage): Contains the puzzle piece’s notch and shadow effects, typically in JPEG format. - Generate Tile Image (
tileImage): The puzzle piece users need to slide, typically in PNG format. - User Interaction: Users slide the puzzle piece to the target position (
TileX,TileY), and the frontend captures the final coordinates. - Verification Logic: The backend compares the user’s slide position with the target position to verify a match.
Code Example
gopackage main import ( "encoding/json" "fmt" "image" "log" "io/ioutil" "github.com/wenlng/go-captcha/v2/base/option" "github.com/wenlng/go-captcha/v2/slide" "github.com/wenlng/go-captcha/v2/base/codec" ) var slideTileCapt slide.Captcha func init() { builder := slide.NewBuilder() // You can use preset material resources:https://github.com/wenlng/go-captcha-assets bgImage, err := loadPng("../resources/bg.png") if err != nil { log.Fatalln(err) } bgImage1, err := loadPng("../resources/bg1.png") if err != nil { log.Fatalln(err) } graphs := getSlideTileGraphArr() builder.SetResources( slide.WithGraphImages(graphs), slide.WithBackgrounds([]image.Image{ bgImage, bgImage1, }), ) slideTileCapt = builder.Make() // drag-drop mode //dragDropCapt = builder.MakeDragDrop() } func getSlideTileGraphArr() []*slide.GraphImage { tileImage1, err := loadPng("../resources/tile-1.png") if err != nil { log.Fatalln(err) } tileShadowImage1, err := loadPng("../resources/tile-shadow-1.png") if err != nil { log.Fatalln(err) } tileMaskImage1, err := loadPng("../resources/tile-mask-1.png") if err != nil { log.Fatalln(err) } return []*slide.GraphImage{ { OverlayImage: tileImage1, ShadowImage: tileShadowImage1, MaskImage: tileMaskImage1, }, } } func main() { captData, err := slideTileCapt.Generate() if err != nil { log.Fatalln(err) } blockData := captData.GetData() if blockData == nil { log.Fatalln(">>>>> generate err") } block, _ := json.Marshal(blockData) fmt.Println(">>>>>", string(block)) var mBase64, tBase64 string mBase64, err = captData.GetMasterImage().ToBase64() if err != nil { fmt.Println(err) } tBase64, err = captData.GetTileImage().ToBase64() if err != nil { fmt.Println(err) } fmt.Println(">>>>> ", mBase64) fmt.Println(">>>>> ", tBase64) //err = captData.GetMasterImage().SaveToFile("../resources/master.jpg", option.QualityNone) //if err != nil { // fmt.Println(err) //} //err = captData.GetTileImage().SaveToFile("../resources/thumb.png") //if err != nil { // fmt.Println(err) //} } func loadPng(p string) (image.Image, error) { imgBytes, err := ioutil.ReadFile(p) if err != nil { return nil, err } return codec.DecodeByteToPng(imgBytes) }
Make Instance
- builder.Make()
- builder.MakeDragDrop()
Configuration Options
slide.NewBuilder(slide.WithXxx(), ...) OR builder.SetOptions(slide.WithXxx(), ...)
| Options | Desc |
|---|---|
| slide.WithImageSize(*option.Size) | Set main image size, default 300x220 |
| slide.WithImageAlpha(float32) | Set main image transparency |
| slide.WithRangeGraphSize(val option.RangeVal) | Set range for random graphic size |
| slide.WithRangeGraphAnglePos([]option.RangeVal) | Set range for random graphic angles |
| slide.WithGenGraphNumber(val int) | Set number of graphics |
| slide.WithEnableGraphVerticalRandom(val bool) | Enable/disable random vertical graphic sorting |
| slide.WithRangeDeadZoneDirections(val []DeadZoneDirectionType) | Set dead zone directions for puzzle pieces |
Set Resources
builder.SetResources(slide.WithXxx(), ...)
| Options | Desc |
|---|---|
| slide.WithBackgrounds([]image.Image) | Set main image backgrounds |
| slide.WithGraphImages(images []*GraphImage) | Set puzzle piece graphics |
Captcha Data
captData, err := capt.Generate()
| Method | Desc |
|---|---|
| GetData() *Block | Get verification data |
| GetMasterImage() imagedata.JPEGImageData | Get main image |
| GetTileImage() imagedata.PNGImageData | Get tile image |
Validate the captcha
ok := slide.Validate(srcX, srcY, X, Y, paddingValue)
| Params | Desc |
|---|---|
| srcX | User X-axis |
| srcY | User Y-axis |
| X | X-axis |
| Y | Y-axis |
| paddingValue | Set the padding value |
Notes
- Puzzle piece image resources (
OverlayImage,ShadowImage,MaskImage) must be valid, otherwiseImageTypeErr,ShadowImageTypeErr, orMaskImageTypeErrwill be triggered. - Background images must not be empty, otherwise
EmptyBackgroundImageErrwill be triggered. - In Basic Mode, the puzzle piece’s Y-coordinate is fixed; in Drag Mode, the Y-coordinate can vary based on
rangeDeadZoneDirections. - Drag Mode is suitable for scenarios requiring higher interaction freedom but may increase user operation time.
🖖 Rotate CAPTCHA
The Rotate CAPTCHA requires users to rotate a thumbnail to align with the main image’s angle, suitable for intuitive interaction scenarios.
How It Works
- Generate Main Image (
masterImage): Contains a rotated background image, typically in PNG format. - Generate Thumbnail (
thumbImage): Cropped from the main image with circular cropping and transparency effects, typically in PNG format. - User Interaction: Users rotate the thumbnail to the target angle (
block.Angle), and the frontend captures the rotation angle. - Verification Logic: The backend compares the user’s rotation angle with the target angle to verify a match.
Code Example
gopackage main import ( "encoding/json" "fmt" "image" "log" "io/ioutil" "github.com/wenlng/go-captcha/v2/rotate" "github.com/wenlng/go-captcha/v2/base/codec" ) var rotateCapt rotate.Captcha func init() { builder := rotate.NewBuilder() // You can use preset material resources:https://github.com/wenlng/go-captcha-assets bgImage, err := loadPng("../resources/bg.png") if err != nil { log.Fatalln(err) } bgImage1, err := loadPng("../resources/bg1.png") if err != nil { log.Fatalln(err) } builder.SetResources( rotate.WithImages([]image.Image{ bgImage, bgImage1, }), ) rotateCapt = builder.Make() } func main() { captData, err := rotateCapt.Generate() if err != nil { log.Fatalln(err) } blockData := captData.GetData() if blockData == nil { log.Fatalln(">>>>> generate err") } block, _ := json.Marshal(blockData) fmt.Println(">>>>>", string(block)) var mBase64, tBase64 string mBase64, err = captData.GetMasterImage().ToBase64() if err != nil { fmt.Println(err) } tBase64, err = captData.GetThumbImage().ToBase64() if err != nil { fmt.Println(err) } fmt.Println(">>>>> ", mBase64) fmt.Println(">>>>> ", tBase64) //err = captData.GetMasterImage().SaveToFile("../resources/master.png") //if err != nil { // fmt.Println(err) //} //err = captData.GetThumbImage().SaveToFile("../resources/thumb.png") //if err != nil { // fmt.Println(err) //} } func loadPng(p string) (image.Image, error) { imgBytes, err := ioutil.ReadFile(p) if err != nil { return nil, err } return codec.DecodeByteToPng(imgBytes) }
Make Instance
- builder.Make()
Configuration Options
rotate.NewBuilder(rotate.WithXxx(), ...) OR builder.SetOptions(rotate.WithXxx(), ...)
| Options | Desc |
|---|---|
| rotate.WithImageSquareSize(val int) | Set main image size, default 220x220 |
| rotate.WithRangeAnglePos(vals []option.RangeVal) | Set range for random verification angles |
| rotate.WithRangeThumbImageSquareSize(val []int) | Set thumbnail size |
| rotate.WithThumbImageAlpha(val float32) | Set thumbnail transparency |
Set Resources
builder.SetResources(rotate.WithXxx(), ...)
| Options | Desc |
|---|---|
| rotate.WithImages([]image.Image) | Set main image backgrounds |
Captcha Data
captData, err := capt.Generate()
| Method | Desc |
|---|---|
| GetData() *Block | Get verification data |
| GetMasterImage() imagedata.PNGImageData | Get main image |
| GetThumbImage() imagedata.PNGImageData | Get thumbnail |
Validate the captcha
ok := rotate.Validate(srcAngle, angle, paddingValue)
| Params | Desc |
|---|---|
| srcAngle | User Angle |
| angle | Angle |
| paddingValue | Set the padding value |
Notes
- Background images must not be empty, otherwise
EmptyImageErrwill be triggered. - Ensure background images are valid
image.Imagetypes, otherwiseImageTypeErrwill be triggered. - Thumbnails are automatically cropped with a circular effect; ensure background images have sufficient resolution to avoid blurriness.
Captcha Image Data
Object Method Of JPEGImageData
| Method | Desc |
|---|---|
| Get() image.Image | |
| ToBytes() ([]byte, error) | |
| ToBytesWithQuality(imageQuality int) ([]byte, error) | |
| ToBase64() (string, error) | |
| ToBase64Data() (string, error) | |
| ToBase64WithQuality(imageQuality int) (string, error) | |
| ToBase64DataWithQuality(imageQuality int) (string, error) | |
| SaveToFile(filepath string, quality int) error |
Object Method Of PNGImageData
| Method | Desc |
|---|---|
| Get() image.Image | |
| ToBytes() ([]byte, error) | |
| ToBase64() (string, error) | |
| ToBase64Data() (string, error) | |
| SaveToFile(filepath string) error |
Language Support
- Golang
- NodeJs
- Rust
- Python
- Java
- PHP
- ...
Web
- JavaScript
- Vue
- React
- Angular
- Svelte
- Solid
- ...
App
- UniApp
- Wx-Applet
- React Native App
- Flutter App
- Android App
- IOS App
- ...
Deployment Service
- Binary Program
- Docker Image
- ...
LICENSE
Go Captcha source code is licensed under the Apache Licence, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.html
Contributors
Showing top 1 contributor by commit count.
