Captcha-Solver in Go: ein funktionierendes Beispiel mit net/http (2026)
Ein Captcha-Solver in Go braucht keine Drittanbieter-Pakete. Die Standardbibliothek net/http und encoding/json decken den ganzen Ablauf ab: ein POST an die Scarnox-API, eine JSON-Antwort und ein Formularabsenden an die Website. Dieser Leitfaden baut diesen Ablauf für PopularCaptcha, das Scarnox heute proxyless löst.
Starten Sie mit einer kostenlosen Testphase, ganz ohne Karte und führen Sie das Programm an einer Seite aus, die Ihnen gehört, bevor Sie es anderswo einsetzen.
Voraussetzungen
- Go 1.21 oder neuer.
- Ein Scarnox-API-Schlüssel, gelesen aus einer Umgebungsvariable.
- Der Sitekey des PopularCaptcha-Widgets der Seite. Wenn Sie Hilfe beim Finden brauchen, siehe wie Sie einen Captcha-Sitekey finden.
Das vollständige Programm
Diese einzelne Datei löst das Captcha, wiederholt vorübergehende Fehler und reicht das Token an das Formular weiter. Speichern Sie sie als main.go:
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/http/cookiejar"
"net/url"
"os"
"time"
)
const apiURL = "https://api.scarnox.com/api/tasks/create"
// Der Lösungsaufruf blockiert, bis das Token bereit ist, daher ist das Timeout lang.
var apiClient = &http.Client{Timeout: 185 * time.Second}
type createRequest struct {
CaptchaType string `json:"captcha_type"`
SiteKey string `json:"site_key"`
SiteURL string `json:"site_url"`
IsInvisible bool `json:"is_invisible,omitempty"`
}
type createResponse struct {
ErrorID int `json:"errorId"`
ErrorCode string `json:"errorCode"`
ErrorDescription string `json:"errorDescription"`
Solution struct {
Token string `json:"token"`
} `json:"solution"`
}
func solveCaptcha(apiKey, sitekey, pageURL string, invisible bool) (string, error) {
body, err := json.Marshal(createRequest{
CaptchaType: "PopularCaptchaTaskProxyless",
SiteKey: sitekey,
SiteURL: pageURL,
IsInvisible: invisible,
})
if err != nil {
return "", err
}
req, err := http.NewRequest(http.MethodPost, apiURL, bytes.NewReader(body))
if err != nil {
return "", err
}
req.Header.Set("Authorization", "Bearer "+apiKey)
req.Header.Set("Content-Type", "application/json")
resp, err := apiClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
raw, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
var out createResponse
if err := json.Unmarshal(raw, &out); err != nil {
return "", fmt.Errorf("HTTP %d, response was not JSON: %s", resp.StatusCode, raw)
}
if out.ErrorID != 0 {
return "", fmt.Errorf("%s: %s", out.ErrorCode, out.ErrorDescription)
}
return out.Solution.Token, nil
}
// solveWithRetry wiederholt vorübergehende Fehler. Fehlgeschlagene Lösungen werden nicht berechnet.
func solveWithRetry(apiKey, sitekey, pageURL string, attempts int) (string, error) {
var lastErr error
for i := 1; i <= attempts; i++ {
token, err := solveCaptcha(apiKey, sitekey, pageURL, false)
if err == nil {
return token, nil
}
lastErr = err
log.Printf("attempt %d failed: %v", i, err)
time.Sleep(time.Duration(i) * time.Second)
}
return "", lastErr
}
func main() {
apiKey := os.Getenv("SCARNOX_API_KEY")
if apiKey == "" {
log.Fatal("set SCARNOX_API_KEY")
}
const pageURL = "https://example.com/signup"
const sitekey = "YOUR-SITEKEY-UUID"
token, err := solveWithRetry(apiKey, sitekey, pageURL, 3)
if err != nil {
log.Fatal(err)
}
// Ein Cookie-Jar hält die Sitzung, an die die Website das Captcha bindet.
jar, err := cookiejar.New(nil)
if err != nil {
log.Fatal(err)
}
site := &http.Client{Jar: jar, Timeout: 60 * time.Second}
form := url.Values{}
form.Set("email", "you@example.com")
form.Set("h-captcha-response", token)
form.Set("g-recaptcha-response", token)
resp, err := site.PostForm(pageURL, form)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
fmt.Println("Status:", resp.Status)
}
Ausführen:
export SCARNOX_API_KEY=scarnox_YOURAPIKEY
go run main.go
Wie die Teile zusammenpassen
Die Anfrage. solveCaptcha wandelt eine Struktur in den JSON-Body um, den die API erwartet, und setzt den Authorization-Header. Das Präfix Bearer ist Pflicht.
Das Timeout. Die API blockiert, bis das Token bereit ist, daher beträgt das Client-Timeout 185 Sekunden. Setzen Sie es nicht niedriger, sonst brechen Sie Lösungen ab, die kurz vor dem Abschluss standen.
Die Fehlerprüfung. Die API liefert errorId als 0 bei Erfolg. Jeder andere Wert kommt mit errorCode und errorDescription, und die Funktion gibt sie als Fehler zurück. Das Token steht unter solution.token.
Das Absenden. Das Token geht in das Feld h-captcha-response, und g-recaptcha-response bekommt denselben Wert. Die meisten Websites lesen das eine oder das andere.
Einen Cookie-Jar verwenden
Viele Registrierungs- und Suchseiten binden das Captcha an eine Sitzung. Der cookiejar am Seiten-Client behält diese Cookies zwischen dem GET, der das Formular zeigt, und dem POST, der es absendet. Lassen Sie ihn weg, kann die Website ein an sich gültiges Token ablehnen.
Timing
Das Token läuft nach etwa zwei Minuten ab, lösen Sie also direkt vor dem Absenden. Lösen Sie nicht zu Beginn eines langen Jobs und warten Sie dann. Ablauf von Captcha-Tokens erklärt, wie Sie das Zeitfenster bemessen.
Unsichtbare Widgets
Wenn das Widget der Seite unsichtbar ist, setzen Sie das Argument invisible auf true. Die Anfrage enthält dann is_invisible: true. Manche Seiten brauchen außerdem einen Callback, der mit dem Token aufgerufen wird. Prüfen Sie das Skript der Seite darauf. Der Leitfaden unsichtbares Captcha listet die Muster auf.
Parallelität
In Go ist es einfach, mit Goroutinen viele Captchas gleichzeitig zu lösen. Halten Sie die Zahl der gleichzeitigen Lösungen in dem Rahmen, den Ihr Konto und die Zielwebsite verkraften. Eine einzelne Domain sollte keinen Schwall von Anfragen bekommen, auch wenn Ihr Solver mithalten könnte. Beachten Sie die robots.txt und die Nutzungsbedingungen der Website und beschränken Sie das Scraping auf öffentliche Daten, die Sie sammeln dürfen.
Preise
Scarnox rechnet pro erfolgreicher Lösung ab. Fehlgeschlagene Lösungen sind kostenlos. Die Tarife finden Sie auf der Preisseite. Um die API zu testen, starten Sie mit einer kostenlosen Testphase, ganz ohne Karte.