# ARCaptcha Consolidated Documentation Context > This document contains the consolidated, complete technical documentation for ARCaptcha. It is optimized for ingestion by Large Language Models and AI coding assistants in a single request. --- ## 1. Overview & Security Architecture ARCaptcha protects web and mobile applications against bots, automated scraping, credential stuffing, SMS fraud, and spam. ### Security Principles: Site Key vs. Secret Key Every ARCaptcha integration relies on two distinct cryptographic keys obtained from the ARCaptcha dashboard (https://dashboard.arcaptcha.co): 1. **Site Key (`site_key`)**: - **Environment**: Client-side (Public). - **Usage**: Configured in HTML markup (`data-site-key="YOUR_SITE_KEY"`) or passed as a parameter in JavaScript `arcaptcha.render()` / SDK components. - **Security**: Publicly accessible in frontend code; identifies your site to ARCaptcha's widget service. 2. **Secret Key (`secret_key`)**: - **Environment**: Server-side (Private). - **Usage**: Used exclusively by your backend server to authenticate token verification requests to `https://api.arcaptcha.co/arcaptcha/api/verify`. - **Security Rule**: NEVER expose the Secret Key in client-side code, mobile application bundles, repository commits, or public scripts. Always store it in server environment variables (e.g., `ARCAPTCHA_SECRET_KEY`). --- ## 2. Integration Flow 1. **Frontend Script Load**: The browser loads the ARCaptcha JavaScript SDK (`https://nwidget.arcaptcha.ir/1/api.js`). 2. **Widget Render**: The widget renders inside a container element with class `arcaptcha` and `data-site-key`. 3. **Challenge Completion**: The user completes the CAPTCHA challenge (interactive or invisible). 4. **Token Generation**: Upon successful challenge resolution, ARCaptcha injects a hidden form input with name `arcaptcha-token` containing the challenge token string. 5. **Form Submission**: The user submits the form. The client sends `arcaptcha-token` along with form data to the customer backend server. 6. **Server Verification**: The customer backend sends a POST request to `https://api.arcaptcha.co/arcaptcha/api/verify` with `site_key`, `secret_key`, and `challenge_id` (the token). 7. **Decision**: The backend inspects the verification response `success` field (`true` or `false`) and allows or blocks the user action accordingly. --- ## 3. Client-Side Integration ### Standard HTML Form Integration ```html ARCaptcha Protected Form
``` ### Mobile WebView Domain Setting When embedding the widget within mobile WebViews, pass the domain parameter in the script tag: ```html ``` ### Bypass Mode and Disaster Recovery The server periodically calls `GET https://api.arcaptcha.ir/arcaptcha/api/heartbeat` and caches the latest result. In a server-rendered app, include the widget script only when the cached result is healthy. In a client-rendered app, the server returns a `loadWidget` instruction and the browser follows it; the browser must not interpret raw heartbeat data as authorization. If loading is denied, skip the widget and do not create a token. The backend uses the same cached result before token verification or outage fallback. In multi-instance deployments, store heartbeat status in shared storage. A verification response with `success: false` is an invalid token and must be rejected. For heartbeat failure, timeouts, network errors, and temporary provider failures, applications may apply an explicit server-side policy: - **Fail-closed (recommended default):** reject or defer the protected action when verification is unavailable. - **Fail-open (opt-in):** allow the action without a verified token; scope this carefully, log decisions without tokens/secrets, rate-limit, and alert. Do not trust a client “heartbeat failed” or “passed” flag or mint a local ARCaptcha token. The [Node.js sample project](https://github.com/arcaptcha/arcaptcha-bypass-mode-demo) periodically caches heartbeat status, simulates heartbeat failure, and uses fail-open only for local demonstration; fail-closed is the safer production default. See [Bypass Mode and Disaster Recovery](https://docs.arcaptcha.co/bypass-mode) for the guide and request-flow diagram. ### Optional: Multi-domain Loader (`init.js`) The standard integration above loads `api.js` directly. As an alternative, use `init.js` to try the v4 widget API on `widget.arcaptcha.ir`, then `.co`, then `.net`. Do not include both scripts on the same page. ```html ``` Each domain attempt has an 8-second timeout by default. If all attempts fail, the loader stops; it does not render a local captcha or issue a failover token. For WebViews, configure `data-api-url` and `data-backup-urls` on the loader script so the `domain` override is retained on each API URL. --- ## 4. Configuration & JavaScript API ### Container Attributes & Render Parameters | Attribute | Render Option | Type / Values | Default | Description | | :--- | :--- | :--- | :--- | :--- | | `data-site-key` | `site_key` | string | (Required) | Public site key. | | `data-size` | `size` | `'normal'` \| `'invisible'` | `'normal'` | Size of the widget. | | `data-theme` | `theme` | `'light'` \| `'dark'` | `'light'` | Color theme. | | `data-color` | `color` | CSS color name or hex | - | Theme accent color. | | `data-error-print` | `error_print` | `'0'` \| `'1'` | `'0'` | Enable (`0`) or disable (`1`) error messages below widget. | | `data-lang` | `lang` | `'en'` \| `'fa'` | `'fa'` | Widget language. | | `data-callback` | `callback` | function / string | - | Triggered upon successful solve. Passes `token`. | | `data-rendered-callback` | `rendered_callback` | function / string | - | Triggered after widget rendering finishes. | | `data-error-callback` | `error_callback` | function / string | - | Triggered upon error during challenge. | | `data-reset-callback` | `reset_callback` | function / string | - | Triggered when widget is reset. | | `data-expired-callback` | `expired_callback` | function / string | - | Triggered when challenge solution expires. | | `data-chlexpired-callback` | `chlexpired_callback` | function / string | - | Triggered when open challenge expires. | | `data-blocked-callback` | `blocked_callback` | function / string | - | Triggered when client is detected as bot. | | `data-clicked-callback` | `clicked_callback` | function / string | - | Triggered when checkbox clicked or `execute` invoked. | | `data-opened-callback` | `opened_callback` | function / string | - | Triggered when challenge modal opens. | | `data-closed-callback` | `closed_callback` | function / string | - | Triggered when challenge modal closes. | ### Global JavaScript Methods (`window.arcaptcha`) 1. `arcaptcha.render(container, params)`: - Explicitly renders the widget inside `container` (DOM selector string or HTMLElement). - `params`: Object with configuration properties (`site_key`, `size`, `callback`, etc.). - Returns: Unique `widgetID`. 2. `arcaptcha.execute(widgetID)`: - Programmatically triggers the ARCaptcha challenge. - Typically used with an Invisible Widget: it starts bot detection and may complete silently or show a pop-up challenge. - Returns a Promise resolving to `{ arcaptcha_token }` or rejecting on failure. 3. `arcaptcha.reset(widgetID)`: - Resets the specified widget (or default widget if omitted) so a new challenge can be solved. 4. `arcaptcha.getArcToken(widgetID)`: - Returns the current challenge token string for the specified widget. --- ## 5. Invisible Widget Invisible Widget removes the “I'm not a robot” checkbox. Calling `arcaptcha.execute()` starts ARCaptcha bot detection: if no human challenge is needed, the callback receives a token without interrupting the user; if an extra check is needed, a pop-up challenge appears first. This is not a reCAPTCHA v3-style score flow; the application does not receive a risk score to interpret. ### Option A: Automatic Button Binding Bind the challenge directly to a submit button: ```html
``` ### Option B: Programmatic Invisible Widget Execution ```html
``` --- ## 6. Server-Side Verification API ### Endpoint Specification - **URL**: `https://api.arcaptcha.co/arcaptcha/api/verify` - **Method**: `POST` - **Headers**: `Content-Type: application/json` ### Request Payload ```json { "site_key": "YOUR_PUBLIC_SITE_KEY", "secret_key": "YOUR_PRIVATE_SECRET_KEY", "challenge_id": "TOKEN_FROM_ARCAPTCHA_TOKEN_POST_DATA" } ``` | Parameter | Type | Required | Description | | :--- | :--- | :--- | :--- | | `site_key` | string | Yes | The site key associated with your domain. | | `secret_key` | string | Yes | Your private account secret key. | | `challenge_id` | string | Yes | The value of `arcaptcha-token` received from the client submission. | ### Response Schema ```json { "success": true, "error-codes": [] } ``` ### Error Codes Reference - `missing-input-sitekey`: The `site_key` parameter is missing. - `missing-input-secret`: The `secret_key` parameter is missing. - `missing-input-response`: The `challenge_id` parameter is missing. - `bad-request`: Malformed or invalid request body. - `invalid-input-sitekey`: The `site_key` parameter is invalid or malformed. - `invalid-input-secret`: The `secret_key` parameter is invalid or malformed. - `invalid-input-response`: The `challenge_id` is invalid, expired, or malformed. - `timeout-or-duplicate`: The challenge has expired or has already been verified. --- ## 7. SDKs & Libraries Catalog ### Frontend Frameworks - **React**: [arcaptcha-react](https://github.com/arcaptcha/Arcaptcha-React-js) (`npm i arcaptcha-react`) - **Vue 2**: [arcaptcha-vue](https://github.com/arcaptcha/arcaptcha-vue) - **Vue 3**: [arcaptcha-vue3](https://github.com/arcaptcha/arcaptcha-vue3) - **Angular**: [arcaptcha-angular](https://github.com/arcaptcha/arcaptcha-angular) - **Flutter**: [arcaptcha-flutter](https://github.com/arcaptcha/arcaptcha-flutter) / [ar_captcha](https://github.com/fateme-shm/ar_captcha) ### Backend SDKs - **Node.js**: [arcaptcha-nodejs](https://github.com/arcaptcha/arcaptcha-nodejs) - **Python**: [arcaptcha-python](https://github.com/arcaptcha/arcaptcha-python) - **Django**: [django-arcaptcha](https://github.com/arcaptcha/django-arcaptcha) - **PHP**: [arcaptcha-php](https://github.com/arcaptcha/arcaptcha-php) - **Laravel**: [arcaptcha-laravel](https://github.com/arcaptcha/arcaptcha-laravel) - **Go**: [arcaptcha-go](https://github.com/arcaptcha/arcaptcha-go) - **C# / .NET**: [Arcaptcha.CSharp](https://github.com/arcaptcha/Arcaptcha.CSharp) - **Ruby**: [arcaptcha-ruby](https://github.com/evokelektrique/arcaptcha-ruby) - **Elixir**: [arcaptcha-elixir](https://github.com/evokelektrique/arcaptcha-elixir) ### Mobile Native - **Android Native**: [arcaptcha-native-android-sdk](https://github.com/arcaptcha/arcaptcha-native-android-sdk) - **Android WebView**: [arcaptcha_android_sdk](https://github.com/arcaptcha/arcaptcha_android_sdk) - **iOS Native**: [ARCaptcha](https://github.com/IbrahimHosseini/ARCaptcha) ### Acknowledgments - **[Ibrahim Hosseini](https://github.com/IbrahimHosseini)** — for developing the native iOS SDK for ARCaptcha. ### CMS Integrations - **WordPress**: [Download Plugin](https://s3.thr1.sotoon.ir/citadel/public/arcaptcha.1.14.zip) - **WordPress Gravity Forms**: [Download Addon](https://s3.thr1.sotoon.ir/citadel/public/gf-arcaptcha-addon.zip) --- ## 8. Server Verification Code Implementations ### Node.js / TypeScript Example ```typescript import axios from "axios"; interface VerifyResponse { success: boolean; "error-codes"?: string[]; } export async function verifyArcaptcha(token: string): Promise { const url = "https://api.arcaptcha.co/arcaptcha/api/verify"; const siteKey = process.env.ARCAPTCHA_SITE_KEY!; const secretKey = process.env.ARCAPTCHA_SECRET_KEY!; try { const response = await axios.post( url, { site_key: siteKey, secret_key: secretKey, challenge_id: token, }, { headers: { "Content-Type": "application/json" }, timeout: 5000, } ); return Boolean(response.data?.success); } catch (error) { console.error("ARCaptcha verification network error:", error); return false; } } ``` ### Python Example ```python import os import requests def verify_arcaptcha(token: str) -> bool: url = "https://api.arcaptcha.co/arcaptcha/api/verify" payload = { "site_key": os.environ["ARCAPTCHA_SITE_KEY"], "secret_key": os.environ["ARCAPTCHA_SECRET_KEY"], "challenge_id": token, } try: res = requests.post( url, json=payload, headers={"Content-Type": "application/json"}, timeout=5, ) data = res.json() return bool(data.get("success", False)) except Exception as exc: print(f"ARCaptcha verification failed: {exc}") return False ``` ### Go Example ```go package main import ( "bytes" "encoding/json" "net/http" "os" "time" ) type VerifyRequest struct { SiteKey string `json:"site_key"` SecretKey string `json:"secret_key"` ChallengeID string `json:"challenge_id"` } type VerifyResponse struct { Success bool `json:"success"` ErrorCodes []string `json:"error-codes,omitempty"` } func VerifyArcaptcha(token string) (bool, error) { client := &http.Client{Timeout: 5 * time.Second} reqBody, err := json.Marshal(VerifyRequest{ SiteKey: os.Getenv("ARCAPTCHA_SITE_KEY"), SecretKey: os.Getenv("ARCAPTCHA_SECRET_KEY"), ChallengeID: token, }) if err != nil { return false, err } resp, err := client.Post( "https://api.arcaptcha.co/arcaptcha/api/verify", "application/json", bytes.NewBuffer(reqBody), ) if err != nil { return false, err } defer resp.Body.Close() var result VerifyResponse if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { return false, err } return result.Success, nil } ``` ### cURL Example ```bash curl -X POST https://api.arcaptcha.co/arcaptcha/api/verify \ -H "Content-Type: application/json" \ -d '{ "site_key": "YOUR_SITE_KEY", "secret_key": "YOUR_SECRET_KEY", "challenge_id": "TOKEN_FROM_FORM" }' ``` ## 9. AI Agent Integration & Onboarding ### 1-Click Prompt ```text Please read https://docs.arcaptcha.co/onboard.md and help me integrate ARCaptcha into this project. ``` ### Supported AI Assistants - **Claude Code**: Terminal invocation (`claude "..."`) and deep link `claude-cli://open?q=...`. - **Cursor**: Composer / Chat prompt injection and deep link `https://cursor.com/link/prompt?text=...`. - **ChatGPT**: Web & desktop session and deep link `https://chatgpt.com/?q=...`. - **OpenCode**: CLI prompt input, automated clipboard copying, and deep link `opencode://open?prompt=...`. ### Security Principles - Never expose `secret_key` in client-side code, git repositories, or frontend bundles. - Keep `secret_key` in server environment variables (e.g. `ARCAPTCHA_SECRET_KEY`). - Provide only `site_key` for client-side HTML containers and widgets.