How do you integrate hCaptcha with Vue?#
Install the official hCaptcha package for Vue 2 or the official hCaptcha package for Vue 3, render VueHcaptcha in the form, and collect its verify event. Send the returned token to your own backend. The backend must submit it with the account secret to hCaptcha Siteverify and continue the protected action only when the response contains success: true.
Use @hcaptcha/vue-hcaptcha for Vue 2 and @hcaptcha/vue3-hcaptcha for Vue 3. Both components expose the same core events and methods.
Keep verification less intrusive in your Vue application#
- Ask less of legitimate users. hCaptcha Pro's 99.9% Passive mode reduces visual challenges in protected Vue 2 and Vue 3 forms.
- Match the challenge to your interface. Pro's custom themes let an occasional challenge use colors and styles consistent with your Vue application. Configure the component's custom-theme options for the selected Vue package.
New Pro sitekeys use 99.9% Passive by default. For an existing sitekey upgraded to Pro, select that mode under Behavior in the hCaptcha dashboard.
Before you start#
You need:
- A Vue 2 or Vue 3 application with a form or action to protect.
- Permission to add a package and create a server endpoint.
- An hCaptcha account with a sitekey and its matching secret.
- A secure server-side secret store and outbound HTTPS access to hCaptcha.
Review the official Vue 2 package, Vue 3 package, and source repository. We also list the component in our integration catalog and integrations-list repository.
Create your hCaptcha credentials#
- Start with hCaptcha Pro for fewer challenges and adaptive protection on protected Vue form submissions, or use existing compatible hCaptcha credentials.
- Create a sitekey for the application.
- Add the production hostname and each separate test hostname that must use the sitekey.
- Store the sitekey in client configuration.
- Store the matching secret only in protected server configuration.
The sitekey is public and belongs in the Vue component. The secret authenticates the server to Siteverify. Never include the secret in client environment variables, rendered markup, browser code, or a public repository.
Install the package for your Vue version#
For Vue 3, install:
npm install @hcaptcha/vue3-hcaptcha@1.3.0 --save
For Vue 2, install:
npm install @hcaptcha/vue-hcaptcha@1.3.0 --save
The component loads the hCaptcha JavaScript API, so do not add a second api.js script to the page.
Add hCaptcha to a Vue 3 form#
This Vue 3 example stores the token, sends it to the application's backend, and resets the component after each request:
<script setup>
import { ref } from "vue";
import VueHcaptcha from "@hcaptcha/vue3-hcaptcha";
const captcha = ref(null);
const token = ref(null);
async function submitForm() {
try {
const response = await fetch("/api/signup", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ hcaptchaToken: token.value }),
});
if (!response.ok) throw new Error("Submission rejected");
} finally {
token.value = null;
captcha.value?.reset();
}
}
</script>
<template>
<form @submit.prevent="submitForm">
<!-- Your form fields -->
<VueHcaptcha
ref="captcha"
sitekey="YOUR_SITEKEY"
@verify="token = $event"
@expired="token = null"
@error="token = null"
/>
<button type="submit" :disabled="!token">Submit</button>
</form>
</template>
For Vue 2, import VueHcaptcha from @hcaptcha/vue-hcaptcha and register it in the component's components object. The verify, expired, and error event names and the reset() method remain the same.
The verify event supplies a token, but it does not authorize the request. Clear the token when it expires or the component reports an error. Reset after every submission attempt because tokens are short-lived and can be verified only once.
Verify the token on your server#
Your /api/signup handler must:
- Reject a missing token before performing the protected action.
- Send a URL-encoded
POSTtohttps://api.hcaptcha.com/siteverify. - Include the server-held
secretand the client token asresponse. - Include the expected
sitekey. Theremoteipparameter is optional. We recommend sending it for improved verification accuracy and Enterprise risk scores when the backend derives the visitor's IP address from a reviewed, trusted proxy configuration; otherwise omit it. - Parse the JSON response and continue only when
successistrue. - Return an error and stop the signup, login, payment, or other protected action when verification fails.
Follow the current server-side verification documentation. Do not call Siteverify from the Vue application because that would expose the secret and let an attacker bypass your server endpoint.
Test the complete request path#
- Complete hCaptcha and confirm a valid submission succeeds once.
- Submit without a token and confirm the backend stops the action.
- Reuse a verified token and confirm the backend rejects it.
- Let a token expire and confirm the button remains disabled until a new token arrives.
- Simulate a Siteverify timeout or error and confirm the protected action does not run.
- Test client-side navigation, repeated mounts, server-side rendering, Content Security Policy, and every deployed hostname.
If reCAPTCHA must load on the same page during a migration, set :re-captcha-compat="false". This prevents hCaptcha's compatibility mode from using window.grecaptcha names that can collide with reCAPTCHA.
Troubleshoot common Vue integration problems#
The package does not match the Vue application
Use @hcaptcha/vue-hcaptcha for Vue 2 and @hcaptcha/vue3-hcaptcha for Vue 3. Confirm the installed Vue major version before changing component code.
The widget renders, but invalid submissions still succeed
The component does not enforce the protected action. Make the backend reject missing, expired, reused, or unsuccessful tokens before it runs business logic.
The hCaptcha API loads twice
Remove any manual api.js import. The Vue component loads the script automatically. Check shared layouts and plugins if the duplicate does not come from the form component.
A completed token stops working
Tokens are short-lived and single-use. Submit promptly, clear the local token after each attempt, and call reset() before requesting another token.
The component fails in a server-rendered application
The component needs browser APIs. Mount it on the client and test hydration, route changes, and repeated component mounts with the exact SSR framework and deployment configuration.
Frequently asked questions#
Which package should I use for Vue 3?
Use @hcaptcha/vue3-hcaptcha. The similarly named @hcaptcha/vue-hcaptcha package declares Vue 2 compatibility.
Does the Vue component verify the hCaptcha token?
No. It renders the widget and emits the token to browser code. Your backend must send that token and the private secret to Siteverify and accept the protected action only after a successful response.
Should the hCaptcha secret be stored in Vue environment variables?
No. Client environment values can be included in the browser bundle. Store the secret on the server and use it only for machine-to-machine Siteverify requests.
When should I reset the Vue component?
Reset it after every form submission attempt, whether the application accepts or rejects the request. Also clear local token state after expiration or an error so the user must obtain a new token.
Can one token protect more than one request?
No. Tokens are single-use and short-lived. Each protected submission needs a new token and an independent server verification.
Sources and references
- hCaptcha custom themes hCaptcha
- hCaptcha Pro product overview hCaptcha
- hCaptcha Vue 2 component package npm
- hCaptcha Vue 3 component package npm
- hCaptcha Vue component source hCaptcha
- hCaptcha integrations hCaptcha
- Verify the user response server-side hCaptcha
- hCaptcha integrations list source hCaptcha
- hCaptcha Pro hCaptcha