{"record":{"id":"88e0b852f182d230","repo":"projectdiscovery/katana","slug":"capsolver-error-s-s","errorCode":null,"errorMessage":"capsolver error %s: %s","messagePattern":"capsolver error (.+?): (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/engine/headless/captcha/capsolver/capsolver.go","lineNumber":132,"sourceCode":"\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tresp, err := s.client.Do(req)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer func() { _ = resp.Body.Close() }()\n\n\trespBody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tvar result createTaskResponse\n\tif err := json.Unmarshal(respBody, &result); err != nil {\n\t\treturn \"\", err\n\t}\n\tif result.ErrorID != 0 {\n\t\treturn \"\", fmt.Errorf(\"capsolver error %s: %s\", result.ErrorCode, result.ErrorDescription)\n\t}\n\treturn result.TaskID, nil\n}\n\nfunc (s *Solver) pollResult(ctx context.Context, taskID string, provider captcha.Provider) (*captcha.Solution, error) {\n\tctx, cancel := context.WithTimeout(ctx, defaultTimeout)\n\tdefer cancel()\n\n\tticker := time.NewTicker(defaultPollInterval)\n\tdefer ticker.Stop()\n\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn nil, fmt.Errorf(\"captcha solve timed out after %s\", defaultTimeout)\n\t\tcase <-ticker.C:\n\t\t\tresult, err := s.getTaskResult(ctx, taskID)\n\t\t\tif err != nil {","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/projectdiscovery/katana/blob/e3e742739c3746f085943ce918fb4e2b8daf6fe6/pkg/engine/headless/captcha/capsolver/capsolver.go#L114-L150","documentation":"capsolver's createTask parses the createTask response and returns 'capsolver error %s: %s' (errorCode, errorDescription) whenever the response's errorId is non-zero. This is the API-level rejection reported by the capsolver service itself, not a transport failure.","triggerScenarios":"POST to /createTask succeeded and returned JSON with errorId != 0 — e.g. ERROR_KEY_DOES_NOT_EXIST, ERROR_ZERO_BALANCE, ERROR_TASK_NOT_SUPPORTED, or invalid task parameters (bad websiteKey/websiteURL).","commonSituations":"Invalid, expired, or revoked capsolver API key; account out of balance; task type not enabled for the account; wrong siteKey or domain in the task payload; enterprise variants used without an enterprise subscription.","solutions":["Read the errorCode/errorDescription in the error and look it up in capsolver's API error docs for the exact cause.","Verify the capsolver API key and account balance; top up or regenerate the key.","Fix task parameters: confirm websiteURL and websiteKey match the target page's captcha configuration.","Confirm the task type (e.g. Enterprise variants) is supported on your capsolver plan.","Fail fast without retry — API rejections are deterministic and retrying the same payload will not help."],"exampleFix":"// before\nsol, err := solver.Solve(ctx, info)\nif err != nil {\n    retry(...) // blindly retries, always fails for bad API key\n}\n// after\nsol, err := solver.Solve(ctx, info)\nif err != nil && strings.Contains(err.Error(), \"capsolver error ERROR_ZERO_BALANCE\") {\n    return nil, fmt.Errorf(\"capsolver account out of balance: %w\", err) // alert ops, don't retry\n}","handlingStrategy":"try-catch","validationCode":"// preflight: validate key format and balance via a cheap call if available\nif !strings.HasPrefix(apiKey, \"CAP-\") { log.Warn(\"capsolver API key looks malformed\") }","typeGuard":null,"tryCatchPattern":"sol, err := solver.Solve(ctx, info)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"capsolver error \") {\n        code := parseCapsolverErrorCode(err)\n        switch code {\n        case \"ERROR_ZERO_BALANCE\":\n            return nil, fmt.Errorf(\"top up capsolver account: %w\", err)\n        case \"ERROR_KEY_DOES_NOT_EXIST\":\n            return nil, fmt.Errorf(\"invalid capsolver API key: %w\", err)\n        default:\n            return nil, err // deterministic API rejection, never retry\n        }\n    }\n    return nil, err\n}","preventionTips":["Verify API key validity and balance before starting captcha-heavy crawls","Match websiteURL/websiteKey exactly to the target page's captcha setup","Never retry on capsolver errorId != 0 — rejections are deterministic","Alert on ERROR_ZERO_BALANCE / ERROR_KEY_DOES_NOT_EXIST as ops issues, not code bugs"],"tags":["captcha","capsolver","api","authentication","go"],"backgroundTag":"captcha-api-error-rejected","analyzedSha":"e3e742739c3746f085943ce918fb4e2b8daf6fe6","analyzedAt":"2026-09-03T14:55:13.248Z","contentChangedAt":"2026-09-03T14:55:13.248Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}