Captcha-solver in Go: werkend voorbeeld met net/http (2026)
Een captcha-solver in Go heeft geen pakketten van derden nodig. De net/http en encoding/json uit de standaardbibliotheek dekken de hele flow: één POST naar de Scarnox-API, één JSON-respons, en één formulierverzending naar de site. Deze gids bouwt die flow voor PopularCaptcha, dat Scarnox vandaag zonder proxy oplost.
Begin met gratis proefcredit, zonder creditcard en draai het programma tegen een pagina die je beheert voordat je het ergens anders gebruikt.
Vereisten
- Go 1.21 of nieuwer.
- Een Scarnox-API-sleutel, gelezen uit een omgevingsvariabele.
- De sitekey van de PopularCaptcha-widget van de pagina. Als je hulp nodig hebt bij het vinden ervan, zie hoe je de captcha-sitekey vindt.
Het volledige programma
Dit ene bestand lost de captcha op, probeert tijdelijke fouten opnieuw en dient het token in bij het formulier. Sla het op 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"
// De oplossingsaanroep blokkeert totdat het token klaar is, dus de time-out is 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 probeert tijdelijke fouten opnieuw. Mislukte oplossingen worden niet in rekening gebracht.
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)
}
// Een cookiejar houdt de sessie vast waaraan de site de captcha koppelt.
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)
}
Uitvoeren:
export SCARNOX_API_KEY=scarnox_YOURAPIKEY
go run main.go
Hoe de onderdelen samenwerken
Het verzoek. solveCaptcha zet een struct om in de JSON-body die de API verwacht en zet de header Authorization. Het voorvoegsel Bearer is verplicht.
De time-out. De API blokkeert totdat het token klaar is, dus de client-time-out is 185 seconden. Zet hem niet lager, anders annuleer je oplossingen die bijna klaar waren.
De foutcontrole. De API geeft errorId als 0 bij succes. Elke andere waarde komt met errorCode en errorDescription, en de functie geeft ze terug als fout. Het token staat in solution.token.
Het verzenden. Het token gaat in het veld h-captcha-response, en g-recaptcha-response krijgt dezelfde waarde. De meeste sites lezen het ene of het andere.
Gebruik een cookiejar
Veel aanmeld- en zoekpagina's koppelen de captcha aan een sessie. De cookiejar op de site-client houdt die cookies vast tussen de GET die het formulier toont en de POST die het verzendt. Als je hem overslaat, kan de site een token weigeren dat anders geldig was.
Timing
Het token verloopt na ongeveer twee minuten, dus los op vlak voordat je verzendt. Los niet op aan het begin van een lange job en wacht daarna. Verlopen captchatokens legt uit hoe je het tijdvenster inschat.
Onzichtbare widgets
Als de widget van de pagina onzichtbaar is, zet het argument invisible dan op true. Het verzoek bevat dan is_invisible: true. Sommige pagina's hebben ook een callbackfunctie nodig die met het token wordt aangeroepen. Controleer het script van de pagina daarvoor. De gids over onzichtbare captcha somt de patronen op.
Gelijktijdigheid
Go maakt het makkelijk om met goroutines veel captchas tegelijk op te lossen. Houd het aantal gelijktijdige oplossingen binnen wat je account en de doelsite aankunnen. Eén domein mag geen uitbarsting van verzoeken krijgen, zelfs als je solver ze kan bijhouden. Respecteer robots.txt en de voorwaarden van de site, en houd het scrapen beperkt tot publieke data die je mag verzamelen.
Prijzen
Scarnox rekent per geslaagde oplossing. Mislukte oplossingen zijn gratis. Zie actuele prijzen voor de tarieven. Om de API uit te proberen, begin je met gratis proefcredit, zonder creditcard.