Go로 reCAPTCHA Enterprise 해결하기
solvethree.com/sdk를 설치하고 대상 호스트 이름, 액션, 프록시로 Solve를 호출하세요. SDK는 작업을 한 번 생성하고 결과를 폴링합니다. 그다음 애플리케이션에서 대상에 토큰을 제출합니다.
이 페이지의 내용
SDK 설치 및 구성
Go 1.22+를 사용하세요. Go 모듈에서 다음을 실행하세요.
go get solvethree.com/sdk@v0.1.0SOLVETHREE_API_KEY를 워크스페이스 API 키로,SOLVETHREE_PROXY를 HTTP(S) 프록시 URL로 설정하세요. 둘 다 서버 설정에 보관하세요.- 워크스페이스에서 대상 호스트 이름에 대한 활성 프로필을 생성하세요. 사이트 프로필 설정을 참고하세요.
accounts.example.com과login을 대상에서 사용하는 호스트 이름과 액션으로 바꾸세요.Site에는 스킴이나 경로 없이 호스트 이름을 지정합니다.
작업 하나 해결하기
이 코드를 main.go로 저장하고 go run .을 실행하세요.
package main
import (
"context"
"fmt"
"log"
"os"
"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)
// Submit result.Solution.Token with its browser identity and original proxy.
}컨텍스트는 로컬 대기 시간을 180초로 제한합니다. Solve는 준비된 TaskResult 또는 오류를 반환하므로 별도의 폴링 루프로 감쌀 필요가 없습니다. 이 요청은 기본 Enterprise v3 모드를 사용합니다. 일반 v3를 사용하려면 RecaptchaType: "v3"를 설정하세요. reCAPTCHA에서는 Type과 URL을 설정하지 마세요.
대상에 토큰 제출하기
애플리케이션의 CAPTCHA 필드에 result.Solution.Token을 보내세요. 출력된 result.ID는 작업을 식별하는 값이며 토큰이 아닙니다.
result.Solution.UserAgent를 User-Agent로, result.Solution.SecChUA를 sec-ch-ua로 사용하세요. solvethree.SuccessfulProxy(input, result)로 선택한, 해결에 성공한 프록시를 통해 대상 요청을 보내세요.
애플리케이션의 나머지 폼 필드, 쿠키, CSRF 값을 포함한 다음 응답을 확인하세요. SDK는 솔루션을 반환할 뿐, 애플리케이션 요청을 대신 제출하지는 않습니다.
대기가 중단되면 ID 보관하기
컨텍스트를 취소하면 로컬 대기만 중단되며 원격 작업은 중단되지 않습니다. *solvethree.Error는 RequestID와 TaskID를 제공합니다. 알고 있는 작업은 GetTask로 조회하세요. 생성 여부가 불확실하면 동일한 RequestID로 원래 입력값을 정확히 다시 보내세요.
프로세스 재시작 후에도 복구하려면 생성 전에 RequestID를 지정하고 작업 입력값과 함께 저장하세요. *TaskFailedError는 최종 실패를 나타냅니다. ErrorCode를 확인하고 작업을 조회해 오류 메시지를 읽으세요. 다른 해결 작업을 시작하기 전에 원인을 수정하세요.
대안: 표준 라이브러리로 REST 호출하기
HTTP 호출을 직접 관리하려면 net/http를 직접 사용하는 이 버전을 이용하세요. 이 예제와 위의 SDK 예제 중 하나를 선택하세요. 둘 다 실행하면 작업이 두 개 생성됩니다. 여기의 응답 구조체는 이 독립 실행형 예제에 속하므로 필드 이름이 SDK 타입과 다릅니다.
package main
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"os"
"time"
)
type Task struct {
ID string `json:"id"`
Status string `json:"status"`
ErrorCode string `json:"errorCode"`
Error string `json:"error"`
Solution struct {
Token string `json:"token"`
UserAgent string `json:"userAgent"`
SecChUa string `json:"secChUa"`
} `json:"solution"`
}
func main() {
key, proxy := os.Getenv("SOLVETHREE_API_KEY"), os.Getenv("SOLVETHREE_PROXY")
if key == "" || proxy == "" { panic("Set SOLVETHREE_API_KEY and SOLVETHREE_PROXY") }
ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
defer cancel()
client := &http.Client{Timeout: 30*time.Second}
api := func(method, path string, body []byte) (Task, error) {
var task Task
req, err := http.NewRequestWithContext(ctx, method, "https://api.solvethree.com/v1"+path, bytes.NewReader(body))
if err != nil { return task, err }
req.Header.Set("Authorization", "Bearer "+key)
req.Header.Set("Content-Type", "application/json")
response, err := client.Do(req)
if err != nil { return task, err }
defer response.Body.Close()
if response.StatusCode < 200 || response.StatusCode >= 300 { return task, fmt.Errorf("API HTTP %d", response.StatusCode) }
err = json.NewDecoder(response.Body).Decode(&task)
return task, err
}
requestID := fmt.Sprintf("go-%d", time.Now().UnixNano())
body, err := json.Marshal(map[string]string{
"site":"accounts.example.com", "action":"login", "proxy":proxy, "requestId":requestID,
})
if err != nil { panic(err) }
// Persist requestID and body before creation if this must survive a restart.
task, err := api(http.MethodPost, "/tasks?waitMs=0", body)
if err != nil { panic(fmt.Errorf("request %s: %w", requestID, err)) }
for task.Status == "pending" || task.Status == "solving" {
task, err = api(http.MethodGet, "/tasks/"+url.PathEscape(task.ID)+"?waitMs=15000", nil)
if err != nil { panic(err) }
if task.Status == "pending" || task.Status == "solving" {
select { case <-ctx.Done(): panic(ctx.Err()); case <-time.After(time.Second): }
}
}
if task.Status != "ready" { panic("Task failed: "+task.ErrorCode+": "+task.Error) }
solution := task.Solution
_ = solution // Apply token and returned browser identity using the same proxy.
fmt.Println("Ready task:", task.ID)
}출처 및 API 레퍼런스
첫 작업을 실행하세요.
워크스페이스 크레딧 $5로 시작하세요.