---
title: Quickstart
---
# Quickstart
This guide will help you integrate CaptchaLa CAPTCHA in 5 minutes.
::: tip See it work in 30 seconds
[demo-v1.captcha.la](https://demo-v1.captcha.la) — pure HTML + PHP, MIT-licensed, view-source on every page.
- [popup.html](https://demo-v1.captcha.la/popup.html) — popup mode
- [float.html](https://demo-v1.captcha.la/float.html) — floating widget
- [bind.html](https://demo-v1.captcha.la/bind.html) — bind to button
- [inline.html](https://demo-v1.captcha.la/inline.html) — inline embed
- [server-token.html](https://demo-v1.captcha.la/server-token.html) — server-issued token (anti-replay)
:::
## 1. Create Account
Sign up for a free account in the dashboard
[Sign Up Now →](https://dash.captcha.la/register)
## 2. Create Application
Create an app in the dashboard to get your App Key
## 3. Install SDK
Choose your preferred installation method
```html
```
```bash
# or via npm
npm install captchala
```
## 4. Initialize CAPTCHA
Initialize the CAPTCHA component in your page
```html
```
## 5. Server Verification
Verify the token on your server
```bash
POST https://apiv1.captcha.la/v1/validate
X-App-Key: YOUR_APP_KEY
X-App-Secret: YOUR_APP_SECRET
Content-Type: application/json
{ "pass_token": "" }
```
```json
{
"code": 0,
"data": {
"valid": true,
"action": "login",
"challenge_id": "ch_xxx",
"uid": null,
"risk_score": 12
}
}
```
::: warning
Always check `data.valid === true` **and** `data.action` matches the scene you expected.
Pass tokens are single-use; the same `pt_xxx` cannot be validated twice.
:::
## Server-issued Token Mode (recommended for production) {#server-token}
For sensitive actions (login, register, payment) we recommend the server-issued token flow: your backend first requests a short-lived server_token, which the browser then uses to initialize the CAPTCHA. This prevents abuse from a leaked app_key.
### When to use
- Recommended: register, login, password reset, payment, points redemption, and any endpoint an attacker can script.
- Optional: casual public forms, search boxes, and low-value interactions where convenience matters more.
### 1. Backend issues server_token
Call /v1/server/challenge/issue from your own server, using the X-App-Key and X-App-Secret headers. Never expose these headers to the browser.
```bash
# Server-side only — never call this from a browser
curl -X POST https://apiv1.captcha.la/v1/server/challenge/issue \
-H "X-App-Key: YOUR_APP_KEY" \
-H "X-App-Secret: YOUR_APP_SECRET" \
-d "action=login&ttl=300&max_uses=1&bind_ip=1.2.3.4"
# → { "code": 0, "data": { "server_token": "sct_...", "expires_in": 300 } }
```
### 2. Frontend renders CaptchaLa with the server_token
Pass the token to your CaptchaLa component. The SDK forwards it to the challenge initialization when initializing the challenge.
```js
// Browser fetches the token from YOUR backend, not from CaptchaLa directly
const { serverToken } = await fetch('/api/captcha/issue').then(r => r.json());
Captchala.init({
appKey: 'YOUR_APP_KEY',
serverToken, // single-use, short-lived
product: 'popup',
action: 'login',
})
.appendTo('#captcha-container')
.onSuccess(res => submitForm(res.token));
```
### Security notes
- Never put app_secret in frontend code, mobile apps, or public repositories. It must stay server-side.
- Enable "Require server-issued challenge token" in the dashboard to reject any challenge attempted without a server_token.
- Keep ttl short (300s default, 900s max) and prefer max_uses=1 to reduce the impact of token leakage.
## Next steps
- [Web SDK](./web-sdk)
- [API Reference](./api-reference)