Use o SDK de Go com chromedp
Primeiro resolva, depois inicie o Chrome com o mesmo proxy e a identidade do navegador retornada. Insira o token no formulário da aplicação, envie-o e aguarde o resultado da aplicação. Uma tarefa pronta significa que você tem uma solução — não que o site a aceitou.
Nesta página
Configure os módulos, o perfil e o proxy
Instale solvethree.com/[email protected] e github.com/chromedp/[email protected] com go get. O SDK exige Go 1.22+, mas esta versão do chromedp exige Go 1.25+, então use essa versão para o exemplo combinado. Sua API tipada difere dos exemplos mais antigos do chromedp.
Crie um perfil de site ativo para o hostname de destino no seu espaço de trabalho antes de executar o programa. Enviar um hostname e uma ação não cria um perfil.
TARGET_URL: a URL HTTPS completa da página que contém seu formulário. A tarefa usa o hostname dela comoSite; o Chrome navega até a URL completa.SOLVETHREE_PROXY: uma única URL de proxy HTTP ou HTTPS. Este exemplo exige um proxy com autorização por IP, sem credenciais na URL.SOLVETHREE_API_KEY: a chave de API do seu espaço de trabalho. Mantenha-a no processo Go, não no JavaScript da página.
O exemplo solicita a ação login e usa o modo padrão reCAPTCHA Enterprise v3. Altere a ação para o valor esperado pela sua aplicação.
Resolva, inicie o Chrome e envie
O programa aguarda a resolução pelo SDK antes de criar o alocador do Chrome. Ele configura o Chrome com o mesmo proxy único e result.Solution.UserAgent, depois define o SecChUA retornado como o cabeçalho sec-ch-ua antes da navegação. Não substitua por uma identidade de navegador sem relação com a solução nem troque de proxy entre a resolução e o envio.
// 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
}Este exemplo usa deliberadamente um único proxy, então não há seleção de candidatos a determinar. Se você passar a usar ProxyCandidates, obtenha o proxy bem-sucedido com SuccessfulProxy(originalTask, readyResult) e use esse proxy no Chrome.
Substitua as premissas do formulário de demonstração
A inserção do token usa json.Marshal antes de construir a expressão JavaScript. Mantenha essa etapa de escape: ela passa o token como um valor de string JavaScript em vez de interpolar texto sem escape em código executável.
- Substitua
[name="g-recaptcha-response"]pelo campo que sua aplicação realmente envia. O exemplo define seu valor e dispara um evento de entrada; adapte isso se sua aplicação precisar de outro fluxo de envio. - Substitua
button[type="submit"]pelo controle de envio desejado. Inclua todos os valores obrigatórios do formulário, campos CSRF e estado da sessão antes de clicar. - Substitua
#successpor um resultado que realmente indique aceitação na sua aplicação. Um clique concluído ou um campo de token preenchido não representa esse resultado.
O SDK não envia o token ao destino. Se o destino rejeitar a requisição, inspecione primeiro o formulário enviado: confirme que ele contém result.Solution.Token, não o ID da tarefa nem um valor anterior do campo, e verifique se o proxy e a identidade do navegador continuam correspondendo.
Trate os prazos sem criar resoluções duplicadas
A resolução tem um prazo de contexto de 180 segundos. O Chrome recebe um prazo separado de 60 segundos após a resolução. A função run retorna erros para que o cancelamento adiado do contexto e a limpeza do navegador sejam executados antes de main registrar um erro.
Cancelar o contexto da resolução interrompe a espera, não o trabalho remoto. O SDK cria a tarefa uma única vez e repete apenas consultas com falhas temporárias; ele nunca repete o POST de criação. Portanto, um tempo limite excedido não é motivo para enviar uma nova tarefa imediatamente.
- Em caso de cancelamento ou prazo excedido, use
errors.Ispara identificar o erro de contexto. Extraia*solvethree.Errorcomerrors.Ase guarde seuTaskIDeRequestID. - Se você tiver um ID de tarefa, recupere-a com
GetTask. Caso contrário, recupere-a reenviando exatamente as entradas originais da tarefa com o mesmo ID de requisição. Chamar novamente sem esse ID cria uma nova requisição lógica; alterar as entradas reutilizando o ID gera um conflito. - Para
*TaskFailedError, inspecioneErrorCodee recupere a tarefa com falha para obter o texto do erro. Essa tarefa está em estado terminal: pare de consultá-la e corrija a causa em vez de tentar novamente com as mesmas entradas. - Para um erro HTTP da API, extraia o
*APIErroraninhado para inspecionarStatusCodeeRetryAfter. Não confunda uma falha HTTP com uma falha terminal da tarefa.
Fontes e referência da API
Execute sua primeira tarefa.
Comece com $5 em créditos no espaço de trabalho.