Skip to content

About

No description, website, or topics provided.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

4 Commits

Folders and files

Repository files navigation

hCaptcha Go integration

Small Go client for hCaptcha Siteverify. It verifies a response token on your server after the browser completes hCaptcha; it does not render the widget or make authorization decisions for you.

Install

go get github.com/hCaptcha/hcaptcha-go/hcaptcha

Requires Go 1.24 or later. Use a supported, patched Go toolchain in production.

Use

This minimal local server uses HCAPTCHA_SECRET and HCAPTCHA_SITEKEY. Create the verifier at startup and reuse it across handlers. Exit before serving requests if either value is missing.

package main

import (
	"log"
	"net/http"
	"os"
	"time"

	hcaptcha "github.com/hCaptcha/hcaptcha-go/hcaptcha"
)

func main() {
	verifier, err := hcaptcha.New(os.Getenv("HCAPTCHA_SECRET"))
	if err != nil {
		log.Fatalf("hcaptcha init failed: %v", err)
	}
	siteKey := os.Getenv("HCAPTCHA_SITEKEY")
	if siteKey == "" {
		log.Fatal("HCAPTCHA_SITEKEY is required")
	}
	http.HandleFunc("POST /protected", func(w http.ResponseWriter, r *http.Request) {
		protected(verifier, siteKey, w, r)
	})
	server := &http.Server{Addr: "127.0.0.1:8080", ReadHeaderTimeout: 5 * time.Second}
	log.Fatal(server.ListenAndServe())
}

func protected(verifier *hcaptcha.Client, siteKey string, w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil {
		http.Error(w, "invalid form", http.StatusBadRequest)
		return
	}
	token := r.PostForm.Get("h-captcha-response")
	if token == "" {
		http.Error(w, "token is required", http.StatusBadRequest)
		return
	}
	result, err := verifier.VerifyRequest(r.Context(), hcaptcha.Request{
		Token:   token,
		SiteKey: siteKey,
	})
	if err != nil {
		http.Error(w, "verification unavailable", http.StatusBadGateway)
		return
	}
	if result["success"] != true {
		http.Error(w, "verification failed", http.StatusForbidden)
		return
	}

	// Perform the protected action.
}

Use Verify(token) for the minimal case. VerifyContext(ctx, token) and VerifyRequest(ctx, request) propagate handler cancellation. Request.Token is required; RemoteIP and SiteKey are optional parameters sent only when non-empty.

New uses a one-second HTTP timeout per attempt; use NewWithHTTPClient to configure it. Request.MaxRetries sets extra attempts after transport errors or HTTP 429/5xx. The default 0 makes one attempt; 2 allows three. Retry delays start at 100 ms, double up to 1 s, and stop on context cancellation.

Production tokens are single-use. The first POST may succeed at hCaptcha even if your server times out before receiving the reply. Retrying the same token can then return already-seen-response; treat it as failure and obtain a fresh token.

Result decodes the Siteverify JSON object into map[string]any. VerifyRequest returns an error for non-2xx HTTP status, transport failure, or invalid JSON. A well-formed 2xx response with success: false has no Go error. Deny the protected action unless result["success"] == true. Inspect error-codes for operational logging; do not expose raw verification details to users.

Browser integration

This package receives the token generated by a browser or mobile integration. Submit the widget's h-captcha-response field to your backend, then call this package from that backend. For the standalone server above, post to /protected and use the value of HCAPTCHA_SITEKEY as the widget sitekey. The runnable React/Vite example below uses VITE_HCAPTCHA_SITEKEY and posts to /api/protected, which Vite proxies to the backend's /protected route.

Use the Developer Guide for the complete browser-to-server flow and the JavaScript configuration reference for explicit rendering, callbacks, themes, and client-side errors.

Security and operations

  • Call Siteverify from the backend with a form-encoded POST. Do not expose the secret or accept a client-side success claim.
  • Verify tokens promptly. hCaptcha tokens are short-lived and single-use.
  • Pass the expected SiteKey to prevent a token issued for another sitekey from being accepted. hostname is informational, not an authentication control.
  • Send RemoteIP when available, using an IP derived from a trusted-proxy policy. Do not trust forwarding headers from arbitrary clients.
  • Enable the hCaptcha domain allowlist when available. Keep the secret in a secret manager or environment variable; rotate a leaked secret immediately.

See hCaptcha’s server-side verification guidance, domain allowlist configuration, and Siteverify error-code reference.

Example and testing

From the repository root, run package tests:

go test ./...

Run the included React/Vite browser and Go backend example:

cd example
cp -n .env.local.example .env.local
npm ci
./run.sh

The sample env uses hCaptcha's public test keys, which skip visual challenges. For real keys, follow the example's development hostname setup; hCaptcha does not support localhost or 127.0.0.1 as hostnames.

About

No description, website, or topics provided.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages