Submit a CAPTCHA token through a Go HTTP proxy
Use a separate Go HTTP client for the target website, configured with the proxy selected by solvethree.SuccessfulProxy. Submit Solution.Token with the returned browser identity. Keep this target transport separate from the SDK client's solvethree API transport.
On this page
Prepare the task
- 1.
Set up the Go SDK and credentials
Use the official
solvethree.com/sdkmodule, versionv0.1.0, with Go 1.22 or later. The Go integration reference has setup details. SetSOLVETHREE_API_KEYto your workspace API key and keep it on the server. SetSOLVETHREE_PROXYto your HTTP or HTTPS proxy URL. - 2.
Configure the site before solving
The workspace needs an active profile for the target hostname. Set up the site profile first; submitting a hostname and action doesn't create one.
- 3.
Replace the example target
Change
accounts.example.com, theloginaction and the application endpoint to match your integration.Siteis a hostname, not a full URL. For reCAPTCHA, supply exactly one ofProxyorProxyCandidates; don't populate the task'sTypeorURLfields. The default reCAPTCHA type is Enterprise v3.
Submit through the proxy that solved the task
package main
import (
"context"
"fmt"
"log"
"os"
"net/http"
"net/url"
"strings"
"time"
solvethree "solvethree.com/sdk"
)
func main() {
client, err := solvethree.NewClient(os.Getenv("SOLVETHREE_API_KEY"), nil)
if err != nil { log.Fatal(err) }
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
defer cancel()
input := solvethree.TaskRequest{Site: "accounts.example.com", Action: "login", Proxy: os.Getenv("SOLVETHREE_PROXY")}
result, err := client.Solve(ctx, input, solvethree.SolveOptions{})
if err != nil { log.Fatal(err) }
fmt.Println("Ready task:", result.ID)
proxy, ok := solvethree.SuccessfulProxy(input, result)
if !ok { log.Fatal("No valid successful proxy") }
proxyURL, err := url.Parse(proxy)
if err != nil { log.Fatal(err) }
transport := http.DefaultTransport.(*http.Transport).Clone()
transport.Proxy = http.ProxyURL(proxyURL)
defer transport.CloseIdleConnections()
targetClient := &http.Client{Transport: transport, Timeout: 30*time.Second,
CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse }}
request, err := http.NewRequestWithContext(ctx, "POST", "https://accounts.example.com/login",
strings.NewReader(url.Values{"g-recaptcha-response": {result.Solution.Token}}.Encode()))
if err != nil { log.Fatal(err) }
request.Header.Set("User-Agent", result.Solution.UserAgent)
request.Header.Set("sec-ch-ua", result.Solution.SecChUA)
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
response, err := targetClient.Do(request)
if err != nil { log.Fatal(err) }
defer response.Body.Close()
fmt.Println("Application HTTP status:", response.StatusCode)
// Inspect the application response to determine whether submission succeeded.
}The SDK solves the task but doesn't submit anything to the website. After solving, the example clones http.DefaultTransport and sets the clone's Proxy through http.ProxyURL. Only the separate targetClient uses that transport; the SDK client's API transport is unchanged.
Keep proxy credentials in the URL's user-info component. url.Parse preserves them for the proxy transport. Percent-encode reserved characters in the username or password rather than splitting the URL manually or sending proxy credentials as a target Authorization header.
Keep the original task input and use SuccessfulProxy even if you currently supply only one proxy. With ProxyCandidates, the successful candidate is identified by Solution.EgressAttempts, a one-based index into the original list. The helper avoids guessing which candidate worked; stop if it returns false. Candidate lists accept at most six distinct HTTP or HTTPS proxy URLs, without a path, query or fragment.
Include the target's headers, form fields and session
The example uses url.Values to form-encode Solution.Token under g-recaptcha-response and sets the matching content type. Replace that field name if your application expects another one. Add the endpoint's other required fields, such as login inputs and any session-bound anti-CSRF value; a CAPTCHA token isn't a complete login request.
Use the returned UserAgent and SecChUA, as the example does. If the solution also supplies entries in Headers, apply those returned headers to the target request too—the example doesn't copy that collection. Keep the browser identity consistent and the content type correct for the body you're sending.
The example has no cookie jar. If the target requires a session, create a jar with net/http/cookiejar, attach it to targetClient.Jar before starting the target flow, and reuse that client for the page request and form submission. Use the same successful proxy throughout that session. The solvethree API client isn't the target's session client.
Check the solve error before accessing the solution. Only a ready task has a usable solution; a failed task's errorCode and error explain that failure. For the target request, handle the error from Do, then check the HTTP status before interpreting the response body. Close response.Body whenever Do returns a response without an error, including non-success HTTP responses.
The example disables automatic redirects and prints the application status. Inspect the response body and any expected redirect to determine whether the application accepted the submission. A ready task—or a successful HTTP status alone—doesn't establish that outcome.
Sources and API reference
Run your first task.
Start with $5 in workspace credit.