API Tutorials

Go Goroutines + CaptchaAI: High-Throughput CAPTCHA Solving

Go's goroutines and channels make it one of the best languages for CAPTCHA solving at scale. Thousands of concurrent solves use minimal memory, and the standard library handles HTTP without external dependencies.


Basic solver

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "net/url"
    "time"
)

const (
    submitURL = "https://ocr.captchaai.com/in.php"
    resultURL = "https://ocr.captchaai.com/res.php"
    apiKey    = "YOUR_API_KEY"
)

type APIResponse struct {
    Status  int    `json:"status"`
    Request string `json:"request"`
}

func solveCaptcha(method string, params map[string]string) (string, error) {
    // Submit
    data := url.Values{
        "key":    {apiKey},
        "method": {method},
        "json":   {"1"},
    }
    for k, v := range params {
        data.Set(k, v)
    }

    resp, err := http.PostForm(submitURL, data)
    if err != nil {
        return "", fmt.Errorf("submit request failed: %w", err)
    }
    defer resp.Body.Close()

    var submitResult APIResponse
    if err := json.NewDecoder(resp.Body).Decode(&submitResult); err != nil {
        return "", fmt.Errorf("submit decode failed: %w", err)
    }

    if submitResult.Status != 1 {
        return "", fmt.Errorf("submit error: %s", submitResult.Request)
    }

    taskID := submitResult.Request

    // Poll
    for i := 0; i < 24; i++ {
        time.Sleep(5 * time.Second)

        pollURL := fmt.Sprintf("%s?key=%s&action=get&id=%s&json=1",
            resultURL, apiKey, taskID)
        pollResp, err := http.Get(pollURL)
        if err != nil {
            continue
        }
        body, _ := io.ReadAll(pollResp.Body)
        pollResp.Body.Close()

        var pollResult APIResponse
        if err := json.Unmarshal(body, &pollResult); err != nil {
            continue
        }

        if pollResult.Status == 1 {
            return pollResult.Request, nil
        }
        if pollResult.Request != "CAPCHA_NOT_READY" {
            return "", fmt.Errorf("poll error: %s", pollResult.Request)
        }
    }

    return "", fmt.Errorf("timeout: task %s", taskID)
}

func main() {
    token, err := solveCaptcha("userrecaptcha", map[string]string{
        "googlekey": "6Le-SITEKEY",
        "pageurl":   "https://example.com",
    })
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }
    fmt.Printf("Token: %.50s...\n", token)
}

Expected output:

Token: 03AGdBq26ZfPxL...

Concurrent solving with WaitGroup

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "net/url"
    "sync"
    "time"
)

const (
    submitURL     = "https://ocr.captchaai.com/in.php"
    resultURL     = "https://ocr.captchaai.com/res.php"
    apiKey        = "YOUR_API_KEY"
    maxConcurrent = 10
)

type APIResponse struct {
    Status  int    `json:"status"`
    Request string `json:"request"`
}

type SolveResult struct {
    Index int
    Token string
    Error error
}

func solveCaptcha(method string, params map[string]string) (string, error) {
    data := url.Values{"key": {apiKey}, "method": {method}, "json": {"1"}}
    for k, v := range params {
        data.Set(k, v)
    }

    resp, err := http.PostForm(submitURL, data)
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    var result APIResponse
    json.NewDecoder(resp.Body).Decode(&result)

    if result.Status != 1 {
        return "", fmt.Errorf(result.Request)
    }

    taskID := result.Request
    for i := 0; i < 24; i++ {
        time.Sleep(5 * time.Second)
        pollResp, err := http.Get(fmt.Sprintf("%s?key=%s&action=get&id=%s&json=1",
            resultURL, apiKey, taskID))
        if err != nil {
            continue
        }
        body, _ := io.ReadAll(pollResp.Body)
        pollResp.Body.Close()

        var pr APIResponse
        json.Unmarshal(body, &pr)
        if pr.Status == 1 {
            return pr.Request, nil
        }
        if pr.Request != "CAPCHA_NOT_READY" {
            return "", fmt.Errorf(pr.Request)
        }
    }
    return "", fmt.Errorf("timeout")
}

func main() {
    var wg sync.WaitGroup
    sem := make(chan struct{}, maxConcurrent)
    results := make(chan SolveResult, 20)

    // Launch 20 concurrent solves
    for i := 0; i < 20; i++ {
        wg.Add(1)
        go func(index int) {
            defer wg.Done()
            sem <- struct{}{}        // acquire
            defer func() { <-sem }() // release

            token, err := solveCaptcha("userrecaptcha", map[string]string{
                "googlekey": fmt.Sprintf("6Le-SITEKEY-%d", index),
                "pageurl":   fmt.Sprintf("https://example.com/page/%d", index),
            })
            results <- SolveResult{Index: index, Token: token, Error: err}
        }(i)
    }

    // Close results channel when all done
    go func() {
        wg.Wait()
        close(results)
    }()

    // Collect results
    solved, failed := 0, 0
    for r := range results {
        if r.Error != nil {
            fmt.Printf("[task-%d] Failed: %v\n", r.Index, r.Error)
            failed++
        } else {
            fmt.Printf("[task-%d] Solved: %.40s...\n", r.Index, r.Token)
            solved++
        }
    }
    fmt.Printf("\nResults: %d solved, %d failed\n", solved, failed)
}

Expected output:

[task-0] Solved: 03AGdBq26ZfPxL...
[task-3] Solved: 03AGdBq27AbCdE...
...
Results: 18 solved, 2 failed

Channel-based worker pool

For production, use a worker pool with input/output channels:

type CaptchaTask struct {
    Index  int
    Method string
    Params map[string]string
}

func worker(id int, tasks <-chan CaptchaTask, results chan<- SolveResult) {
    for task := range tasks {
        token, err := solveCaptcha(task.Method, task.Params)
        results <- SolveResult{Index: task.Index, Token: token, Error: err}
    }
}

func runWorkerPool(taskList []CaptchaTask, workerCount int) []SolveResult {
    tasks := make(chan CaptchaTask, len(taskList))
    results := make(chan SolveResult, len(taskList))

    // Start workers
    for i := 0; i < workerCount; i++ {
        go worker(i, tasks, results)
    }

    // Send tasks
    for _, t := range taskList {
        tasks <- t
    }
    close(tasks)

    // Collect results
    var all []SolveResult
    for i := 0; i < len(taskList); i++ {
        all = append(all, <-results)
    }
    return all
}

HTTP client tuning

Use a shared client with connection pooling:

var client = &http.Client{
    Transport: &http.Transport{
        MaxIdleConns:        100,
        MaxIdleConnsPerHost: 50,
        IdleConnTimeout:     30 * time.Second,
    },
    Timeout: 15 * time.Second,
}

Replace http.PostForm and http.Get with client.PostForm and client.Get.


Troubleshooting

Problem Cause Fix
connection reset Too many concurrent connections Lower maxConcurrent, tune MaxIdleConnsPerHost
Goroutine leak No timeout on HTTP calls Set http.Client.Timeout
All tasks timeout API under load Increase poll loop from 24 to 36 iterations
Panic on closed channel Writing to closed results channel Ensure close() is called after all writes

FAQ

How many goroutines can I run?

Go supports thousands of goroutines. The limiting factor is CaptchaAI's concurrency limit, not Go. Use the semaphore pattern to match your account's capacity.

Should I use goroutines or the worker pool pattern?

Use goroutines with semaphore for simple batches. Use the worker pool for long-running services where tasks arrive continuously.

How does this compare to Python asyncio?

Go goroutines are lighter than Python coroutines and handle more concurrent I/O with less overhead. For pure HTTP-based CAPTCHA solving, Go is typically 2-3x faster at high concurrency.


Start high-throughput CAPTCHA solving with CaptchaAI

Get your API key at captchaai.com.


Discussions (0)

No comments yet.

Related Posts

API Tutorials CaptchaAI API Latency Optimization: Faster Solves
Reduce CAPTCHA solve latency with Captcha AI by optimizing poll intervals, connection pooling, prefetching, and proxy selection.

Reduce CAPTCHA solve latency with Captcha AI by optimizing poll intervals, connection pooling, prefetching, an...

Automation Python reCAPTCHA v2
Feb 27, 2026
Reference CAPTCHA Token Injection Methods Reference
Complete reference for injecting solved CAPTCHA tokens into web pages.

Complete reference for injecting solved CAPTCHA tokens into web pages. Covers re CAPTCHA, Turnstile, and Cloud...

Automation Python reCAPTCHA v2
Apr 08, 2026
Tutorials Pytest Fixtures for CaptchaAI API Testing
Build reusable pytest fixtures to test CAPTCHA-solving workflows with Captcha AI.

Build reusable pytest fixtures to test CAPTCHA-solving workflows with Captcha AI. Covers mocking, live integra...

Automation Python reCAPTCHA v2
Apr 08, 2026
Reference Browser Session Persistence for CAPTCHA Workflows
Manage browser sessions, cookies, and storage across CAPTCHA-solving runs to reduce repeat challenges and maintain authenticated state.

Manage browser sessions, cookies, and storage across CAPTCHA-solving runs to reduce repeat challenges and main...

Automation Python reCAPTCHA v2
Feb 24, 2026
Integrations Browser Profile Isolation + CaptchaAI Integration
Browser profile isolation tools create distinct browser environments with unique fingerprints per session.

Browser profile isolation tools create distinct browser environments with unique fingerprints per session. Com...

Automation Python reCAPTCHA v2
Feb 21, 2026
Comparisons WebDriver vs Chrome DevTools Protocol for CAPTCHA Automation
Compare Web Driver and Chrome Dev Tools Protocol (CDP) for CAPTCHA automation — detection, performance, capabilities, and when to use each with Captcha AI.

Compare Web Driver and Chrome Dev Tools Protocol (CDP) for CAPTCHA automation — detection, performance, capabi...

Automation Python reCAPTCHA v2
Mar 27, 2026
Use Cases CAPTCHA Solving in Ticket Purchase Automation
How to handle CAPTCHAs on ticketing platforms Ticketmaster, AXS, and event sites using Captcha AI for automated purchasing workflows.

How to handle CAPTCHAs on ticketing platforms Ticketmaster, AXS, and event sites using Captcha AI for automate...

Automation Python reCAPTCHA v2
Feb 25, 2026
Use Cases Event Ticket Monitoring with CAPTCHA Handling
Build an event ticket availability monitor that handles CAPTCHAs using Captcha AI.

Build an event ticket availability monitor that handles CAPTCHAs using Captcha AI. Python workflow for checkin...

Automation Python reCAPTCHA v2
Jan 17, 2026
Tutorials Caching CAPTCHA Tokens for Reuse
Cache and reuse CAPTCHA tokens with Captcha AI to reduce API calls and costs.

Cache and reuse CAPTCHA tokens with Captcha AI to reduce API calls and costs. Covers token lifetimes, cache st...

Automation Python reCAPTCHA v2
Feb 15, 2026
API Tutorials How to Solve reCAPTCHA v2 Callback Using API
how to solve re CAPTCHA v 2 callback implementations using Captcha AI API.

Learn how to solve re CAPTCHA v 2 callback implementations using Captcha AI API. Detect the callback function,...

Automation reCAPTCHA v2 Webhooks
Mar 01, 2026
API Tutorials Solve GeeTest v3 CAPTCHA with Python and CaptchaAI
Step-by-step Python tutorial for solving Gee Test v 3 slide puzzle CAPTCHAs using the Captcha AI API.

Step-by-step Python tutorial for solving Gee Test v 3 slide puzzle CAPTCHAs using the Captcha AI API. Includes...

Automation Python Testing
Mar 23, 2026
API Tutorials Case-Sensitive CAPTCHA API Parameter Guide
How to use the regsense parameter for case-sensitive CAPTCHA solving with Captcha AI.

How to use the regsense parameter for case-sensitive CAPTCHA solving with Captcha AI. Covers when to use, comm...

Python Web Scraping Image OCR
Apr 09, 2026