Utiliser le SDK Go avec chromedp

Par solvethree4 min de lecture

Effectuez d’abord la résolution, puis lancez Chrome avec le même proxy et l’identité de navigateur renvoyée. Insérez le jeton dans le formulaire de l’application, envoyez-le et attendez le résultat de l’application. Une tâche prête signifie que vous disposez d’une solution, pas que le site web l’a acceptée.

Sur cette page

Configurer les modules, le profil et le proxy

Installez solvethree.com/[email protected] et github.com/chromedp/[email protected] avec go get. Le SDK nécessite Go 1.22+, mais cette version de chromedp nécessite Go 1.25+ : utilisez donc cette version pour l’exemple combiné. Son API typée diffère de celle des anciens exemples chromedp.

Créez un profil de site actif pour le nom d’hôte cible dans votre espace de travail avant d’exécuter le programme. L’envoi d’un nom d’hôte et d’une action ne crée pas de profil.

  • TARGET_URL : l’URL HTTPS complète de la page contenant votre formulaire. La tâche utilise son nom d’hôte comme Site ; Chrome accède à l’URL complète.
  • SOLVETHREE_PROXY : une seule URL de proxy HTTP ou HTTPS. Cet exemple nécessite un proxy autorisé par liste d’adresses IP, sans identifiants dans l’URL.
  • SOLVETHREE_API_KEY : la clé API de votre espace de travail. Conservez-la dans le processus Go, et non dans le JavaScript de la page.

L’exemple demande l’action login et utilise le mode reCAPTCHA Enterprise v3 par défaut. Remplacez l’action par la valeur attendue par votre application.

Résoudre, lancer Chrome et envoyer

Le programme attend la résolution du SDK avant de créer l’allocateur de Chrome. Il configure Chrome avec le même proxy unique et result.Solution.UserAgent, puis définit le SecChUA renvoyé comme en-tête sec-ch-ua avant la navigation. Ne substituez pas une identité de navigateur sans rapport et ne changez pas de proxy entre la résolution et l’envoi.

chromedp · soumettre via un proxy autorisé par adresse IP
// go get github.com/chromedp/[email protected] (requires Go 1.25+)
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "log"
    "net/url"
    "os"
    "time"
    "github.com/chromedp/cdproto/network"
    "github.com/chromedp/chromedp"
    solvethree "solvethree.com/sdk"
)

func main() { if err := run(); err != nil { log.Fatal(err) } }

func run() error {
    target,err:=url.Parse(os.Getenv("TARGET_URL"));if err!=nil||target.Scheme!="https"||target.Hostname()=="" { return fmt.Errorf("set an HTTPS TARGET_URL") }
    proxy,err:=url.Parse(os.Getenv("SOLVETHREE_PROXY"));if err!=nil||proxy.User!=nil { return fmt.Errorf("use an IP-allowlisted proxy without URL credentials") }
    client,err:=solvethree.NewClient(os.Getenv("SOLVETHREE_API_KEY"),nil);if err!=nil { return err }
    ctx,cancel:=context.WithTimeout(context.Background(),180*time.Second);defer cancel()
    result,err:=client.Solve(ctx,solvethree.TaskRequest{Site:target.Hostname(),Action:"login",Proxy:proxy.String()},solvethree.SolveOptions{})
    if err!=nil { return err }
    options:=append(chromedp.DefaultExecAllocatorOptions[:],chromedp.ProxyServer(proxy.String()),chromedp.UserAgent(result.Solution.UserAgent))
    allocator,closeAllocator:=chromedp.NewExecAllocator(context.Background(),options...);defer closeAllocator()
    browser,closeBrowser:=chromedp.NewContext(allocator);defer closeBrowser()
    browser,stop:=context.WithTimeout(browser,60*time.Second);defer stop()
    tokenJSON,err:=json.Marshal(result.Solution.Token);if err!=nil { return err }
    script:=`(token => {const field=document.querySelector('[name="g-recaptcha-response"]'); field.value=token; field.dispatchEvent(new Event('input',{bubbles:true}));})(`+string(tokenJSON)+`)`
    _,err=chromedp.Call(browser,network.SetExtraHTTPHeaders,network.SetExtraHTTPHeadersParams{Headers:network.Headers{"sec-ch-ua":result.Solution.SecChUA}})
    if err!=nil { return err }
    err=chromedp.Do(browser,
        chromedp.Navigate(target.String()),chromedp.WaitReady(chromedp.CSS(`[name="g-recaptcha-response"]`)),
        chromedp.Evaluate[chromedp.Void](script),chromedp.Click(chromedp.CSS(`button[type="submit"]`)),
        chromedp.WaitVisible(chromedp.ID("success")))
    if err!=nil { return err }
    // #success is this owned demo form's outcome. Adapt its selectors, token
    // parameter and success check to your application, including CSRF/session fields.
    return nil
}

Cet exemple utilise délibérément un seul proxy : aucun choix entre candidats n’est donc nécessaire. Si vous utilisez ensuite ProxyCandidates, obtenez le proxy ayant réussi avec SuccessfulProxy(originalTask, readyResult) et utilisez ce proxy pour Chrome.

Adapter les hypothèses du formulaire de démonstration

L’insertion du jeton utilise json.Marshal avant de construire l’expression JavaScript. Conservez cette étape d’échappement : elle transmet le jeton comme valeur de chaîne JavaScript au lieu d’interpoler du texte non échappé dans du code exécutable.

  • Remplacez [name="g-recaptcha-response"] par le champ réellement envoyé par votre application. L’exemple définit sa valeur et déclenche un événement input ; adaptez ce comportement si votre application nécessite une autre méthode d’envoi.
  • Remplacez button[type="submit"] par le contrôle d’envoi voulu. Renseignez les valeurs de formulaire, les champs CSRF et l’état de session nécessaires avant de cliquer.
  • Remplacez #success par un résultat qui indique réellement l’acceptation dans votre application. Un clic effectué ou un champ de jeton renseigné ne constitue pas ce résultat.

Le SDK n’envoie pas le jeton à la cible. Si la cible rejette la requête, examinez d’abord le formulaire envoyé : vérifiez qu’il contient result.Solution.Token, et non l’ID de la tâche ou une ancienne valeur du champ, et que le proxy et l’identité du navigateur correspondent toujours.

Gérer les échéances sans créer de résolutions en double

La résolution dispose d’une échéance de contexte de 180 secondes. Chrome dispose d’une échéance distincte de 60 secondes après la résolution. La fonction run renvoie les erreurs afin que l’annulation différée de son contexte et le nettoyage du navigateur s’exécutent avant que main ne consigne une erreur.

L’annulation du contexte de résolution arrête l’attente, pas le travail distant. Le SDK effectue une seule création et ne réessaie que les interrogations ayant échoué temporairement ; il ne réessaie jamais le POST de création. Un dépassement de délai ne justifie donc pas l’envoi immédiat d’une nouvelle tâche.

  • En cas d’annulation ou d’échéance atteinte, utilisez errors.Is pour identifier l’erreur de contexte. Extrayez *solvethree.Error avec errors.As et conservez ses TaskID et RequestID.
  • Si vous disposez d’un ID de tâche, récupérez la tâche avec GetTask. Sinon, retrouvez-la en renvoyant exactement les paramètres de la tâche d’origine avec le même ID de requête. Un nouvel appel sans cet ID crée une nouvelle requête logique ; modifier les paramètres tout en réutilisant cet ID provoque un conflit.
  • Pour *TaskFailedError, examinez ErrorCode et récupérez la tâche en échec pour obtenir son texte d’erreur. Cette tâche est dans un état définitif : cessez de l’interroger et corrigez la cause au lieu de réessayer avec des paramètres inchangés.
  • Pour une erreur HTTP de l’API, extrayez le *APIError imbriqué afin d’examiner StatusCode et RetryAfter. Ne confondez pas un échec HTTP avec un échec définitif de tâche.

Lancez votre première tâche.

Démarrez avec $5 de crédit dans votre espace de travail.

Créer un espace de travail
Utiliser le SDK Go avec chromedp · solvethree