Go

Copy sdk/go/privcaptcha.go into your project. Standard library only.

Verify

client := privcaptcha.New(os.Getenv("PRIVCAPTCHA_SECRET"))

result, err := client.Verify(ctx, r.FormValue("privcaptcha-response"), r.RemoteAddr)
if err != nil || !result.Success {
    http.Error(w, "captcha failed", http.StatusBadRequest)
    return
}
type Client struct {
    Secret   string
    Endpoint string       // defaults to https://privcaptcha.com/api/v1/siteverify
    HTTP     *http.Client // defaults to a 10s timeout
}

func New(secret string) *Client
func (c *Client) Verify(ctx context.Context, response, remoteIP string) (*Result, error)

Result is {Success, ChallengeTS, Hostname, ErrorCodes}, decoded straight from the API response.

Fail-closed behaviour

An unreachable verifier, a non-200 status or an undecodable body returns ErrUnavailable. Treat it as a failure, never as a pass — "we could not check" must not resolve to "allowed". Always test err != nil before reading result.

An empty response returns &Result{Success: false, ErrorCodes: ["missing-input-response"]} with a nil error and no network call, so check Success as well as err.

Pass a request-scoped ctx so a slow verification cannot outlive the request that needs it.