Go
Solve captchas from Go.
The helper below uses only the standard library (net/http and encoding/json). It
submits a task with POST /createTask, polls POST /getTaskResult until the status is
ready, and returns an error if the API reports a failure or the timeout is exceeded.
The example solves a Cloudflare Turnstile challenge.
Keep your key out of source control
Read the API key from an environment variable rather than hardcoding it. Set it once
with export NOCAPTCHAAI_KEY="your-key" (get one at
nocaptchaai.com/manage).
package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"time"
)
const baseURL = "https://api.nocaptchaai.com"
func postJSON(path string, body any) (map[string]any, error) {
payload, err := json.Marshal(body)
if err != nil {
return nil, err
}
resp, err := http.Post(baseURL+path, "application/json", bytes.NewReader(payload))
if err != nil {
return nil, err
}
defer resp.Body.Close()
var out map[string]any
if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
return nil, err
}
return out, nil
}
// Solve creates a task, polls until it is ready, and returns the solution.
func Solve(apiKey string, task map[string]any, pollInterval, timeout time.Duration) (map[string]any, error) {
created, err := postJSON("/createTask", map[string]any{"clientKey": apiKey, "task": task})
if err != nil {
return nil, err
}
if created["errorId"] != nil && created["errorId"] != float64(0) {
return nil, fmt.Errorf("createTask failed: %v", created)
}
taskID, ok := created["taskId"].(string)
if !ok {
return nil, fmt.Errorf("createTask returned no taskId: %v", created)
}
deadline := time.Now().Add(timeout)
for {
result, err := postJSON("/getTaskResult", map[string]any{"clientKey": apiKey, "taskId": taskID})
if err != nil {
return nil, err
}
switch result["status"] {
case "ready":
solution, _ := result["solution"].(map[string]any)
return solution, nil
case "failed":
return nil, fmt.Errorf("task failed: %v", result)
}
if result["errorId"] != nil && result["errorId"] != float64(0) {
return nil, fmt.Errorf("task failed: %v", result)
}
if time.Now().After(deadline) {
return nil, errors.New("timed out waiting for task " + taskID)
}
time.Sleep(pollInterval)
}
}
func main() {
apiKey := os.Getenv("NOCAPTCHAAI_KEY")
task := map[string]any{
"type": "AntiTurnstileTask",
"websiteURL": "https://example.com",
"websiteKey": "0x4AAAAAAA...",
}
solution, err := Solve(apiKey, task, 3*time.Second, 120*time.Second)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", solution)
}Call Solve() with any task map — swap the type, websiteURL, and websiteKey for
the captcha you need to solve. The returned solution map contains the token (and any
other fields) you submit back to the target site.