Go Captcha Solver
Solve image CAPTCHAs in Go with pure stdlib — no external packages needed. FastCaptcha returns the answer in 0.3–0.7 seconds with 95% accuracy.
Go Quick Start
No go get required — pure net/http and encoding/json
Basic solve
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
"path/filepath"
)
const apiKey = "YOUR_API_KEY"
type APIResponse struct {
Success bool `json:"success"`
Text string `json:"text"`
Confidence float64 `json:"confidence"`
ProcessingTime float64 `json:"processing_time"`
Error string `json:"error"`
}
func SolveCaptcha(imagePath string) (string, error) {
file, err := os.Open(imagePath)
if err != nil {
return "", err
}
defer file.Close()
var buf bytes.Buffer
writer := multipart.NewWriter(&buf)
part, _ := writer.CreateFormFile("image", filepath.Base(imagePath))
io.Copy(part, file)
writer.Close()
req, _ := http.NewRequest("POST",
"https://fastcaptcha.org/api/v1/ocr/", &buf)
req.Header.Set("X-API-Key", apiKey)
req.Header.Set("Content-Type", writer.FormDataContentType())
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
var result APIResponse
json.NewDecoder(resp.Body).Decode(&result)
if !result.Success {
return "", fmt.Errorf("API error: %s", result.Error)
}
return result.Text, nil
}
With retry & context timeout
import (
"context"
"math"
"math/rand"
"time"
)
func SolveWithRetry(imagePath string) (string, error) {
maxRetries := 4
for attempt := 0; attempt < maxRetries; attempt++ {
text, err := SolveCaptcha(imagePath)
if err == nil {
return text, nil
}
// Only retry on transient errors
errStr := err.Error()
retriable := strings.Contains(errStr, "429") ||
strings.Contains(errStr, "500") ||
strings.Contains(errStr, "503")
if !retriable || attempt == maxRetries-1 {
return "", err
}
delay := math.Min(
math.Pow(2, float64(attempt))+rand.Float64(),
32,
)
fmt.Printf("Retrying in %.1fs (attempt %d)\n", delay, attempt+1)
time.Sleep(time.Duration(delay * float64(time.Second)))
}
return "", fmt.Errorf("max retries exceeded")
}
// With context timeout (recommended)
func SolveWithTimeout(imagePath string) (string, error) {
ctx, cancel := context.WithTimeout(
context.Background(), 15*time.Second)
defer cancel()
req, _ := http.NewRequestWithContext(ctx, "POST", ...)
// ... rest same as above
}
Concurrent solving with goroutines
func SolveBatch(imagePaths []string, concurrency int) []string {
sem := make(chan struct{}, concurrency) // limit concurrency
results := make([]string, len(imagePaths))
var wg sync.WaitGroup
for i, path := range imagePaths {
wg.Add(1)
go func(idx int, p string) {
defer wg.Done()
sem <- struct{}{}
defer func() { <-sem }()
text, err := SolveWithRetry(p)
if err != nil {
fmt.Printf("Error on %s: %v\n", p, err)
return
}
results[idx] = text
}(i, path)
}
wg.Wait()
return results
}
// Usage:
// results := SolveBatch(images, 5) // 5 concurrent requests
⚡
0.3s avg
Sub-second responses on image CAPTCHAs
📦
Zero deps
Pure stdlib — no external packages
🔀
Goroutine-safe
Safe for concurrent use across goroutines