Tutorials

Solve CAPTCHAs with Go Using CaptchaAI

Go's concurrency model and fast HTTP performance make it ideal for high-volume CAPTCHA solving. This tutorial shows you how to build a reusable CaptchaAI client in Go.

Requirements

Requirement Details
Go 1.21+
Dependencies Standard library only
CaptchaAI API key Get one here

CaptchaAI Client

package captchaai

import (
    "encoding/base64"
    "fmt"
    "io"
    "net/http"
    "net/url"
    "os"
    "strings"
    "time"
)

type Client struct {
    APIKey     string
    BaseURL    string
    HTTPClient *http.Client
}

func NewClient(apiKey string) *Client {
    return &Client{
        APIKey:  apiKey,
        BaseURL: "https://ocr.captchaai.com",
        HTTPClient: &http.Client{
            Timeout: 30 * time.Second,
        },
    }
}

// Submit sends a CAPTCHA task and returns the task ID.
func (c *Client) Submit(params map[string]string) (string, error) {
    params["key"] = c.APIKey

    u, _ := url.Parse(c.BaseURL + "/in.php")
    q := u.Query()
    for k, v := range params {
        q.Set(k, v)
    }
    u.RawQuery = q.Encode()

    resp, err := c.HTTPClient.Get(u.String())
    if err != nil {
        return "", fmt.Errorf("submit request failed: %w", err)
    }
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)
    text := string(body)

    if !strings.HasPrefix(text, "OK|") {
        return "", fmt.Errorf("submit error: %s", text)
    }

    return strings.SplitN(text, "|", 2)[1], nil
}

// Poll waits for the CAPTCHA result with a timeout.
func (c *Client) Poll(taskID string, timeout time.Duration) (string, error) {
    deadline := time.Now().Add(timeout)

    params := url.Values{
        "key":    {c.APIKey},
        "action": {"get"},
        "id":     {taskID},
    }

    pollURL := c.BaseURL + "/res.php?" + params.Encode()

    for time.Now().Before(deadline) {
        time.Sleep(5 * time.Second)

        resp, err := c.HTTPClient.Get(pollURL)
        if err != nil {
            continue
        }

        body, _ := io.ReadAll(resp.Body)
        resp.Body.Close()
        text := string(body)

        if text == "CAPCHA_NOT_READY" {
            continue
        }

        if strings.HasPrefix(text, "OK|") {
            return strings.SplitN(text, "|", 2)[1], nil
        }

        return "", fmt.Errorf("solve error: %s", text)
    }

    return "", fmt.Errorf("timeout after %v for task %s", timeout, taskID)
}

// Solve submits and polls in one call.
func (c *Client) Solve(params map[string]string) (string, error) {
    taskID, err := c.Submit(params)
    if err != nil {
        return "", err
    }
    return c.Poll(taskID, 5*time.Minute)
}

// GetBalance returns the account balance in USD.
func (c *Client) GetBalance() (string, error) {
    params := url.Values{
        "key":    {c.APIKey},
        "action": {"getbalance"},
    }

    resp, err := c.HTTPClient.Get(c.BaseURL + "/res.php?" + params.Encode())
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)
    return string(body), nil
}

Solve reCAPTCHA v2

package main

import (
    "fmt"
    "os"
)

func main() {
    client := captchaai.NewClient(os.Getenv("CAPTCHAAI_API_KEY"))

    token, err := client.Solve(map[string]string{
        "method":    "userrecaptcha",
        "googlekey": "6Le-wvkS...",
        "pageurl":   "https://example.com",
    })
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        os.Exit(1)
    }

    fmt.Printf("Token: %s\n", token)
}

Solve reCAPTCHA v3

token, err := client.Solve(map[string]string{
    "method":    "userrecaptcha",
    "googlekey": "6Le-wvkS...",
    "pageurl":   "https://example.com",
    "version":   "v3",
    "action":    "login",
})

Solve Cloudflare Turnstile

token, err := client.Solve(map[string]string{
    "method":  "turnstile",
    "sitekey": "0x4AAAAA...",
    "pageurl": "https://example.com",
})

Solve Image CAPTCHAs

import "encoding/base64"

imgBytes, _ := os.ReadFile("captcha.png")
imgB64 := base64.StdEncoding.EncodeToString(imgBytes)

text, err := client.Solve(map[string]string{
    "method": "base64",
    "body":   imgB64,
})

fmt.Printf("Recognized: %s\n", text)

Concurrent Solving with Goroutines

Go's goroutines make parallel CAPTCHA solving easy:

package main

import (
    "fmt"
    "os"
    "sync"
)

type Task struct {
    SiteKey string
    PageURL string
}

func main() {
    client := captchaai.NewClient(os.Getenv("CAPTCHAAI_API_KEY"))

    tasks := []Task{
        {"6Le-wvkS...", "https://example.com/page1"},
        {"6Le-wvkS...", "https://example.com/page2"},
        {"6Le-wvkS...", "https://example.com/page3"},
    }

    var wg sync.WaitGroup
    results := make([]string, len(tasks))

    for i, task := range tasks {
        wg.Add(1)
        go func(idx int, t Task) {
            defer wg.Done()
            token, err := client.Solve(map[string]string{
                "method":    "userrecaptcha",
                "googlekey": t.SiteKey,
                "pageurl":   t.PageURL,
            })
            if err != nil {
                fmt.Fprintf(os.Stderr, "Task %d error: %v\n", idx, err)
                return
            }
            results[idx] = token
        }(i, task)
    }

    wg.Wait()

    for i, r := range results {
        if r != "" {
            fmt.Printf("Task %d: solved (%d chars)\n", i, len(r))
        }
    }
}

Using with net/http Requests

Inject solved tokens into form submissions:

func submitForm(client *captchaai.Client, targetURL, siteKey string) error {
    token, err := client.Solve(map[string]string{
        "method":    "userrecaptcha",
        "googlekey": siteKey,
        "pageurl":   targetURL,
    })
    if err != nil {
        return err
    }

    form := url.Values{
        "g-recaptcha-response": {token},
        "username":             {"testuser"},
    }

    resp, err := http.PostForm(targetURL, form)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    fmt.Printf("Form response: %d\n", resp.StatusCode)
    return nil
}

Troubleshooting

Error Cause Fix
submit request failed: dial tcp: lookup ocr.captchaai.com: no such host DNS issue Check network/DNS settings
submit error: ERROR_WRONG_USER_KEY Bad API key Verify key from dashboard
timeout after 5m0s Long solve time Increase timeout duration
submit error: ERROR_ZERO_BALANCE No funds Top up account balance

FAQ

Can I use this in a CLI tool?

Yes. The client uses only the standard library. Compile to a single binary with go build.

How many goroutines can safely run in parallel?

CaptchaAI handles high concurrency. 50-100 parallel solves is safe. For higher volumes, use a worker pool with a semaphore channel.

Should I reuse the Client across goroutines?

Yes. The Client struct is safe for concurrent use since http.Client is goroutine-safe.

Discussions (0)

No comments yet.

Related Posts

API Tutorials Building a Go Client Library for CaptchaAI API
Build a Go client library for the Captcha AI API — idiomatic Go with context cancellation, custom HTTP client support, typed solver methods, and proper error ha...

Build a Go client library for the Captcha AI API — idiomatic Go with context cancellation, custom HTTP client...

Automation All CAPTCHA Types Go
Mar 23, 2026
DevOps & Scaling Ansible Playbooks for CaptchaAI Worker Deployment
Deploy and manage Captcha AI workers with Ansible — playbooks for provisioning, configuration, rolling updates, and health checks across your server fleet.

Deploy and manage Captcha AI workers with Ansible — playbooks for provisioning, configuration, rolling updates...

Automation Python All CAPTCHA Types
Apr 07, 2026
DevOps & Scaling Blue-Green Deployment for CAPTCHA Solving Infrastructure
Implement blue-green deployments for CAPTCHA solving infrastructure — zero-downtime upgrades, traffic switching, and rollback strategies with Captcha AI.

Implement blue-green deployments for CAPTCHA solving infrastructure — zero-downtime upgrades, traffic switchin...

Automation Python All CAPTCHA Types
Apr 07, 2026
Troubleshooting CaptchaAI API Error Handling: Complete Decision Tree
Complete decision tree for every Captcha AI API error.

Complete decision tree for every Captcha AI API error. Learn which errors are retryable, which need parameter...

Automation Python All CAPTCHA Types
Mar 17, 2026
Tutorials Using Fiddler to Inspect CaptchaAI API Traffic
How to use Fiddler Everywhere and Fiddler Classic to capture, inspect, and debug Captcha AI API requests and responses — filters, breakpoints, and replay for tr...

How to use Fiddler Everywhere and Fiddler Classic to capture, inspect, and debug Captcha AI API requests and r...

Automation Python All CAPTCHA Types
Mar 05, 2026
Tutorials CAPTCHA Handling in Mobile Apps with Appium
Handle CAPTCHAs in mobile app automation using Appium and Captcha AI — extract Web sitekeys, solve, and inject tokens on Android and i OS.

Handle CAPTCHAs in mobile app automation using Appium and Captcha AI — extract Web View sitekeys, solve, and i...

Automation Python All CAPTCHA Types
Feb 13, 2026
Tutorials Streaming Batch Results: Processing CAPTCHA Solutions as They Arrive
Process CAPTCHA solutions the moment they arrive instead of waiting for tasks to complete — use async generators, event emitters, and callback patterns for stre...

Process CAPTCHA solutions the moment they arrive instead of waiting for all tasks to complete — use async gene...

Automation Python All CAPTCHA Types
Apr 07, 2026
Reference CaptchaAI CLI Tool: Command-Line CAPTCHA Solving and Testing
A reference for building and using a Captcha AI command-line tool — solve CAPTCHAs, check balance, test parameters, and integrate with shell scripts and CI/CD p...

A reference for building and using a Captcha AI command-line tool — solve CAPTCHAs, check balance, test parame...

Automation Python All CAPTCHA Types
Feb 26, 2026
DevOps & Scaling Auto-Scaling CAPTCHA Solving Workers
Build auto-scaling CAPTCHA solving workers that adjust capacity based on queue depth, balance, and solve rates.

Build auto-scaling CAPTCHA solving workers that adjust capacity based on queue depth, balance, and solve rates...

Automation Python All CAPTCHA Types
Mar 23, 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
Tutorials GeeTest Token Injection in Browser Automation Frameworks
how to inject Gee Test v 3 solution tokens into Playwright, Puppeteer, and Selenium — including the three-value response, callback triggering, and form submissi...

Learn how to inject Gee Test v 3 solution tokens into Playwright, Puppeteer, and Selenium — including the thre...

Automation Python Testing
Jan 18, 2026