Skip to content

hCaptcha

hCaptcha is a CAPTCHA service that can be used to bypass rate limiting when legitimate users are affected.

Schema Integration

hCaptcha uses the same GraphQL schema integration as other CAPTCHA providers:

enum CaptchaType {
HCAPTCHA # hCaptcha
TURNSTILE # Cloudflare Turnstile
V2_VISIBLE # reCAPTCHA v2 with visible checkbox
V2_INVISIBLE # reCAPTCHA v2 without visible elements
}
type CaptchaConfiguration {
type: CaptchaType!
siteKey: String!
}

Implementation Examples

Successful Registration with hCaptcha

When users complete hCaptcha verification, the token can bypass rate limiting:

mutation CreateAccount($input: CreateAccountInput!) {
createAccount(input: $input) {
success
account {
id
email
firstName
lastName
}
error
fieldErrors {
fieldName
validators
requiredButNotProvided
invalidOption
}
}
}

Request Headers:

X-Captcha-Type: HCAPTCHA
X-Captcha-Response: P1_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
Content-Type: application/json

Rate Limited Response with hCaptcha Configuration

When rate limits are exceeded, hCaptcha configuration is provided:

{
"data": {
"createAccount": null
},
"errors": [
{
"message": "Too many registration attempts",
"path": ["createAccount"],
"extensions": {
"classification": "CAPTCHA_REQUIRED",
"rateLimited": true,
"rateLimitingBucket": "REGISTRATION"
}
}
],
"extensions": {
"rateLimitersFiring": [
{
"captchaBypassAvailable": [
{
"type": "HCAPTCHA",
"siteKey": "12345678-1234-1234-1234-123456789012"
}
],
"rateLimitingBucket": "REGISTRATION"
}
]
}
}

Error Handling

Common hCaptcha error responses:

Error CodeDescription
missing-input-responseNo token provided
invalid-input-responseInvalid token
missing-input-secretServer configuration issue
invalid-input-secretInvalid secret key
expired-input-responseToken has expired
sitekey-secret-mismatchKey configuration mismatch

API Usage

Both web and mobile APIs support hCaptcha using the same header pattern:

// Web API
fetch('https://horizon-api.www.myprotein.com/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Captcha-Type': 'HCAPTCHA',
'X-Captcha-Response': hcaptchaToken
},
credentials: 'include',
body: JSON.stringify({ query, variables })
});
// Mobile API
fetch('https://api.thehut.net/myprotein/en/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Captcha-Type': 'HCAPTCHA',
'X-Captcha-Response': hcaptchaToken,
'Authorization': 'Opaque ' + userToken
},
body: JSON.stringify({ query, variables })
});