From c8a15484fc739cb967a821febac47a4249d7e450 Mon Sep 17 00:00:00 2001 From: Hugh Parry Date: Tue, 25 Aug 2026 08:46:19 +0100 Subject: [PATCH] docs: add an error reference for every widget-visible error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documents each error message Procaptcha can display in place of the widget, with the translated string, the stable translation key, the HTTP status, and — for each — what it means, what causes it, and how to clear it. The set is derived from what actually reaches the screen (state.error.message into Checkbox, and fallOverWithStyle for frictionless) rather than from the locale file, which is much broader. Errors thrown inside providerRetry go to console.error and never render, and PoW/puzzle submit returns { status: "ok", verified: false } with no message, so the IP-category block reasons (VPN_BLOCKED, TOR_BLOCKED, ...) are deliberately excluded — they are deferred to submit/verify time and belong with the siteverify ResultReason values. API.FAILED_IP_VALIDATION is likewise omitted: validateSessionIP unconditionally returns valid. The six error Q&As in the FAQ now give a one-line answer and link into the detailed section so the prose lives in one place. Corrects "Session not found" to "No session found" (the actual string) and adds an entry for the case where the widget fails silently to the console. Incorrect CAPTCHA type is written around its real causes (direct API integrations, old bundles, stale sessions, captchaType-pinning access rules) rather than the data-captcha-type advice in captcha-types.mdx, which current bundles ignore. That page needs a separate fix. Claude-Session: https://claude.ai/code/session_01DLYQU7po3wAWsppeaUrU7b --- .../docs/en/basics/error-reference.mdx | 347 ++++++++++++++++++ src/content/docs/en/basics/faq.mdx | 49 +-- src/i18n/en/nav.ts | 5 + 3 files changed, 379 insertions(+), 22 deletions(-) create mode 100644 src/content/docs/en/basics/error-reference.mdx diff --git a/src/content/docs/en/basics/error-reference.mdx b/src/content/docs/en/basics/error-reference.mdx new file mode 100644 index 0000000000000..1887483f3d87b --- /dev/null +++ b/src/content/docs/en/basics/error-reference.mdx @@ -0,0 +1,347 @@ +--- +title: Error Reference +description: Every error message Procaptcha can display in place of the widget, what causes it, and how to clear it. +i18nReady: true +--- + +When Procaptcha cannot show a challenge, it replaces the widget with a short error message. This page lists every +message a visitor can see, what causes it, and what to do about it. + +## Reading an error + +Each error has two identities: + +- **The message**, e.g. `Site key not registered`. This is what your visitor sees, and it is translated into their + language. A German visitor sees `Site Key nicht registriert` for the same error. +- **The key**, e.g. `API.SITE_KEY_NOT_REGISTERED`. This never changes and is never translated, so it is what you should + search for, log, and quote to support. + +The message is on screen. To find the key, open your browser's developer tools, go to the **Network** tab, reload the +page, and look at the response from the request to `/v1/prosopo/provider/client/captcha/…`: + +```json +{ + "error": { + "message": "Site key not registered", + "key": "API.SITE_KEY_NOT_REGISTERED", + "code": 400 + } +} +``` + +:::note[The error callback receives the message, not the key] +The `error-callback` you configure on the widget is called with a standard `Error` whose `message` is the translated +string. If you want to branch on a specific error in your own code, read the `key` from the network response rather +than matching on message text, which changes with the visitor's language. +::: + +## Quick reference + +| Message | Key | Whose problem is it? | +| --- | --- | --- | +| `Site key not registered` | `API.SITE_KEY_NOT_REGISTERED` | [Your configuration](#site-key-not-registered) | +| `Invalid site key` | `API.INVALID_SITE_KEY` | [Your configuration](#invalid-site-key) | +| `Unauthorized origin URL` | `API.UNAUTHORIZED_ORIGIN_URL` | [Your configuration](#unauthorized-origin-url) | +| `Incorrect CAPTCHA type` | `API.INCORRECT_CAPTCHA_TYPE` | [Usually your configuration](#incorrect-captcha-type) | +| `Procaptcha requires a secure (HTTPS) connection` | `WIDGET.INSECURE_CONTEXT` | [Your configuration](#procaptcha-requires-a-secure-https-connection) | +| `No session found` | `CAPTCHA.NO_SESSION_FOUND` | [Transient, self-healing](#no-session-found) | +| `Cannot load CAPTCHA` | *(none)* | [Transient, self-healing](#cannot-load-captcha) | +| `Frictionless response missing captchaType; halting captcha mount` | *(none)* | [This visitor was blocked](#frictionless-response-missing-captchatype-halting-captcha-mount) | +| `Forbidden: ` | *(none)* | [This visitor was blocked](#forbidden-request-id) | +| `Error parsing captcha` | `CAPTCHA.PARSE_ERROR` | [Unexpected](#error-parsing-captcha) | +| `BadRequest` | `API.BAD_REQUEST` | [Unexpected](#badrequest) | + +## Configuration errors + +These come from how your site key or your markup is set up, so they usually affect **every** visitor, including you. +If you can reproduce the error yourself, it is almost certainly one of these. Fix them in the +[Prosopo portal](https://portal.prosopo.io) or in your widget markup. + +### Site key not registered + +**Key:** `API.SITE_KEY_NOT_REGISTERED` · **HTTP:** 400 + +**What it means.** The site key in your widget is a valid, well-formed key, but Prosopo has no record of it. + +**What causes it.** + +- Your account was created but never activated, so the site key was issued and not yet enabled. +- The site key was deleted from your account, or belongs to an account that has been closed. +- You copied a site key from an example, a tutorial, or another organisation's site. +- You are pointing a production site key at a development environment, or vice versa. + +**How to fix it.** + +1. Check your email for the Prosopo activation link and click it. This is the cause the majority of the time. +2. Log in to the [Prosopo portal](https://portal.prosopo.io) and confirm the site key is listed and active. +3. Copy the site key straight from the portal into your `data-sitekey` attribute — do not retype it. +4. If the key is listed as active and the error persists, + [contact support](mailto:support@prosopo.io) quoting the site key. + +### Invalid site key + +**Key:** `API.INVALID_SITE_KEY` · **HTTP:** 400 + +**What it means.** The value you supplied is not a well-formed Prosopo site key at all, so it was rejected before any +lookup happened. This is a different failure from [`Site key not registered`](#site-key-not-registered), where the key +was well-formed but unknown. + +**What causes it.** + +- A truncated or partially copied key. +- Stray whitespace, quotes, or a trailing comma inside the `data-sitekey` attribute. +- A template placeholder that was never substituted, such as `data-sitekey="{{ SITE_KEY }}"`. +- Your **secret** key pasted where the **site** key belongs. The secret key is for server-side verification only and + must never appear in your HTML. + +**How to fix it.** + +1. Log in to the [Prosopo portal](https://portal.prosopo.io) and copy the site key. +2. Confirm your rendered HTML contains the full key with no surrounding whitespace: + + ```html +
+ ``` + +3. If you inject the key from a server-side template or an environment variable, view the page source in the browser + and confirm the variable was actually interpolated. + +### Unauthorized origin URL + +**Key:** `API.UNAUTHORIZED_ORIGIN_URL` · **HTTP:** 400 + +**What it means.** The site key is valid and registered, but the domain the widget is running on is not on that key's +list of allowed domains. + +**What causes it.** + +- The site is being served from a domain you have not added yet — commonly a staging, preview, or branch-deploy URL. +- A `www.` versus bare-domain mismatch, or a country domain you did not register alongside the main one. +- Local development on `localhost` or `127.0.0.1` with a site key registered only for production. +- The widget is embedded in an iframe hosted on a third-party domain, which makes the *embedding* domain the origin. + +**How to fix it.** + +1. Log in to the [Prosopo portal](https://portal.prosopo.io) and open the site key's settings. +2. Add the exact domain shown in your browser's address bar to the allowed domains. +3. Add every domain you deploy to, not just production — staging and preview URLs each need an entry. +4. Reload the page. Domain changes take effect immediately. + +### Incorrect CAPTCHA type + +**Key:** `API.INCORRECT_CAPTCHA_TYPE` · **HTTP:** 400 + +**What it means.** A challenge was requested for one [captcha type](/en/basics/captcha-types) when Prosopo expected a +different one. Current versions of the widget are told which type to use by the server, so this points either at a +client that bypassed that step, or at a stale session. + +**What causes it.** + +- **A direct API integration** requesting `/captcha/pow`, `/captcha/image`, or `/captcha/puzzle` for a type that does + not match the one configured on the site key in the portal. +- **A very old copy of the Procaptcha bundle** that still honours a `data-captcha-type` attribute on your markup and + requests that type directly. Current bundles ignore the attribute entirely. +- **A stale session.** The widget carried on with a session whose type no longer matches — for example a page restored + from the browser's back/forward cache, or a challenge that was escalated to a second stage the host page did not + follow. +- **An access control rule** pinning a specific captcha type for this visitor that differs from the one requested. + +**How to fix it.** + +1. If a visitor hits this once and a refresh clears it, it was a stale session. No configuration change is needed. +2. Make sure you are loading the current Procaptcha bundle. If your markup still carries `data-captcha-type`, remove + it — the type is chosen by Prosopo and the attribute has no effect on current bundles. +3. If you integrate against the API directly, request the captcha type that the site key is configured for in the + [Prosopo portal](https://portal.prosopo.io). +4. If it is persistent for one visitor but not others, check your + [access control rules](/en/advanced/access-control-rules) for a rule pinning a captcha type. + +### Procaptcha requires a secure (HTTPS) connection + +**Key:** `WIDGET.INSECURE_CONTEXT` · **HTTP:** *(no request is made)* + +**What it means.** The page is not running in a [secure browser context](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts). +Procaptcha depends on browser cryptography APIs that browsers only expose over HTTPS, so it stops immediately rather +than failing later with a confusing message. + +**What causes it.** + +- The page was loaded over plain `http://`. +- A local development server bound to a LAN address such as `http://192.168.1.10:3000`. Browsers treat `localhost` as + secure, but not other IP addresses. +- The page is embedded in an iframe served over plain HTTP, which makes the whole context insecure. + +**How to fix it.** + +1. Serve the page over HTTPS. In production this is required, not optional. +2. In local development, use `http://localhost` (which browsers already treat as secure) rather than a LAN IP. +3. If you must test from another device on your network, put a local HTTPS proxy or tunnel in front of your dev server. + +## Transient errors + +These clear on their own. Neither one means anything is misconfigured, and neither needs action from your visitor +beyond waiting. + +### No session found + +**Key:** `CAPTCHA.NO_SESSION_FOUND` · **HTTP:** 400 + +**What it means.** The widget tried to continue a challenge whose session the provider no longer holds. Sessions are +single-use and time-limited by design. + +**What causes it.** + +- The visitor left the page open long enough for the session to expire before interacting with the widget. +- The page was restored from the browser's back/forward cache with a session that had already been used. +- The visitor's browser blocked or cleared the storage the widget uses to hold the session. + +**How to fix it.** + +1. Do nothing. The widget detects this specific error and automatically resets itself after about 10 seconds, at which + point the visitor can solve a fresh challenge. +2. If the visitor is impatient, refreshing the page resolves it immediately. +3. If it happens on *every* attempt and never recovers, clear the browser's cache and cookies and try again, then + [contact support](https://discord.com/invite/3nMYAHecZT). + +### Cannot load CAPTCHA + +**Key:** *(none — this is a fallback message)* · **HTTP:** *(varies)* + +**What it means.** The widget tried five times to reach a Prosopo provider and failed each time, or it received a +failure with no message attached. This is the generic last-resort message shown when nothing more specific is known. + +**What causes it.** + +- A transient network problem between the visitor and Prosopo. +- The visitor's network, corporate proxy, DNS filter, or browser extension is blocking requests to Prosopo. +- A Content Security Policy on your site that does not allow the widget to reach Prosopo. +- A provider-side incident. + +**How to fix it.** + +1. Do nothing first. The widget reloads itself roughly 10 seconds after giving up, and transient failures usually clear + on the retry. +2. If it is reproducible, open developer tools and check the **Network** tab and **Console** for blocked requests. A CSP + violation or an `ERR_BLOCKED_BY_CLIENT` entry points at a policy or extension on the visitor's side rather than at + Prosopo. +3. Check that your Content Security Policy permits the widget's requests to Prosopo. +4. If requests are reaching Prosopo and still failing for many visitors, + [contact support](https://discord.com/invite/3nMYAHecZT). + +## Blocked visitors + +These two messages mean Prosopo refused the request outright. Only the affected visitor sees them; the rest of your +traffic is unaffected. If your own rules caused the block, this is Procaptcha working as configured. + +:::note[These messages are deliberately vague] +Neither message names the rule that fired. That is intentional — telling an automated client exactly why it was blocked +helps it evade the block. Use the audit log in the portal to see the real reason. +::: + +### Frictionless response missing captchaType; halting captcha mount + +**Key:** *(none)* · **HTTP:** 401 + +**What it means.** Prosopo returned `401 Unauthorized` rather than a challenge, and the widget refused to guess what to +show. The visitor was turned away before any captcha was issued. + +**What causes it.** + +- An [access control rule](/en/advanced/access-control-rules) on your site matched this visitor and is set to block. +- The visitor's bot score exceeded your site's auto-ban threshold. +- The request failed a header integrity check, which usually means it did not come from a genuine browser. + +**How to fix it.** + +- **If this is a real visitor being blocked wrongly**, review your + [access control rules](/en/advanced/access-control-rules) and your + [safety threshold](/en/basics/safety-threshold) in the portal. A threshold set too aggressively is the most common + cause of false positives. +- **If you are testing with a script, `curl`, or a headless browser**, this is the expected outcome. Automated clients + are what the block exists to stop. +- **If you cannot tell which it is**, check the audit log for your site in the + [Prosopo portal](https://portal.prosopo.io) — it records which rule fired for each blocked request. See + [Audit](/en/advanced/audit). + +### Forbidden: `` + +**Key:** *(none)* · **HTTP:** 403 + +**What it means.** The request matched an entry on Prosopo's blocklist and was rejected at the edge, before it reached +any captcha logic. The trailing value is the request ID. + +**What causes it.** + +- The visitor's IP address, network, or client fingerprint is on a blocklist. +- The request came from infrastructure Prosopo has classified as abusive. + +**How to fix it.** + +1. Copy the request ID from the end of the message. It uniquely identifies this request in our logs. +2. If you believe a genuine visitor was blocked, [contact support](https://discord.com/invite/3nMYAHecZT) and quote the + request ID. We can look up the exact rule that fired. +3. Do not ask visitors to retry — a blocklist match will produce the same result every time. + +## Unexpected errors + +If you see either of these, something went wrong that should not have. They are worth reporting. + +### Error parsing captcha + +**Key:** `CAPTCHA.PARSE_ERROR` · **HTTP:** 400 + +**What it means.** Prosopo received a request from the widget that it could not read — a required field was missing, +or a value was not of the expected shape. + +**What causes it.** + +- A modified, out-of-date, or partially loaded copy of the Procaptcha bundle. +- Something on the page or in the network path altering the widget's requests, such as an aggressive optimisation + proxy or a browser extension. +- A client that is imitating the widget rather than being the widget. + +**How to fix it.** + +1. Make sure you are loading the Procaptcha bundle from the official URL and are not pinning an old copy. +2. Hard-refresh (`Ctrl`-`Shift`-`R`) to rule out a stale cached bundle. +3. Reproduce with browser extensions disabled. +4. If it persists on a clean, current bundle, [contact support](https://discord.com/invite/3nMYAHecZT). + +### BadRequest + +**Key:** `API.BAD_REQUEST` · **HTTP:** 400 or 500 + +**What it means.** A catch-all for a request Prosopo could not fulfil. When it carries a 500 it indicates a +provider-side failure rather than anything about your request. + +**What causes it.** + +- A required request header, such as `Origin`, was missing or stripped in transit. +- An internal provider error while building the challenge. + +**How to fix it.** + +1. Retry. Where the cause is provider-side, the widget's own retry usually succeeds against a different provider. +2. Check whether a proxy or CDN in front of your site is stripping the `Origin` header from browser requests. +3. If it is consistent and reproducible, [contact support](https://discord.com/invite/3nMYAHecZT) with the URL and the + time of the failure. + +## Errors that never reach the visitor + +Not every Procaptcha error is displayed. Some are written only to the browser console, so a visitor reporting "the +captcha just doesn't appear" may be hitting one of these. Check the console before assuming a network problem. + +| Console message | Key | Meaning | +| --- | --- | --- | +| `No site key found` | — | The widget element has no `data-sitekey` attribute at all. Add one. | +| `SITE KEY missing` | `GENERAL.SITE_KEY_MISSING` | The widget started without a site key available to it. Same fix. | +| `No Procaptcha containers found for execution` | — | `execute()` was called but no element with the `procaptcha` class exists on the page. | +| `No captchas returned from provider` | `DEVELOPER.PROVIDER_NO_CAPTCHA` | The provider returned an empty challenge. The widget retries automatically. | + +Separately, a visitor who fails a challenge is not shown an error at all — the widget simply resets so they can try +again. Nothing is broken in that case. + +## Still stuck? + +Have your site key and, if you have one, the request ID to hand, then reach us on +[Discord](https://discord.com/invite/3nMYAHecZT) or at [support@prosopo.io](mailto:support@prosopo.io). diff --git a/src/content/docs/en/basics/faq.mdx b/src/content/docs/en/basics/faq.mdx index 5fd308baa2aed..3413cee90f6b7 100644 --- a/src/content/docs/en/basics/faq.mdx +++ b/src/content/docs/en/basics/faq.mdx @@ -4,34 +4,39 @@ description: Common questions and answers about Procaptcha. i18nReady: true --- -### What does `Site Key not Registered` mean? -You may encounter this error when you set up the Procaptcha widget on your website. This error occurs when the site key -you are using is not registered in the Prosopo system. To resolve this error, click the Activation link in the email -or contact the Prosopo support team. +Looking for a specific error message shown in place of the widget? The [Error Reference](/en/basics/error-reference) +covers every one of them, with causes and fixes. -### What does `Invalid Site Key` mean? -This error occurs when the site key you are using is not valid. To resolve this error, ensure that you are using the -correct site key, which you can find by logging in to the [Prosopo portal](https://portal.prosopo.io). +### What does `Site key not registered` mean? +The site key you are using is not registered in the Prosopo system. Most often the account was never activated — click +the activation link in your email, or contact the Prosopo support team. +See [Site key not registered](/en/basics/error-reference#site-key-not-registered). + +### What does `Invalid site key` mean? +The value in your `data-sitekey` attribute is not a well-formed site key — usually truncated, or a placeholder that was +never substituted. Copy the key from the [Prosopo portal](https://portal.prosopo.io). +See [Invalid site key](/en/basics/error-reference#invalid-site-key). ### What does `Unauthorized origin URL` mean? -This error occurs when the domain of the site key does not match the domain of the website where the Procaptcha widget -is being used. To resolve this error, ensure that the domain of the site key matches the domain of the website by -logging in to the [Prosopo portal](https://portal.prosopo.io) and updating the domain. +The domain serving the widget is not on the site key's list of allowed domains. Add it in the +[Prosopo portal](https://portal.prosopo.io), including any staging and preview domains. +See [Unauthorized origin URL](/en/basics/error-reference#unauthorized-origin-url). ### What does `Incorrect CAPTCHA type` mean? -This error occurs when the [captcha type](/en/basics/captcha-types) is not set correctly. The default `captchaType` is -`frictionless`. If you wish to use `pow` or `image` you must set your `captchaType` in the widget configuration to `pow` -or `image`. You must also update your [portal settings](https://portal.prosopo.io) to match. +The [captcha type](/en/basics/captcha-types) your widget requests does not match the one configured for the site key. +The default is `frictionless`; if you set `pow`, `image`, or `puzzle` in your markup you must set the same value in your +[portal settings](https://portal.prosopo.io). +See [Incorrect CAPTCHA type](/en/basics/error-reference#incorrect-captcha-type). -### What does `Session not found` mean? -This error occurs when the session is not found. This can happen if the session has expired or if the session ID is -not valid. To resolve this error, either wait for the widget to reload (3s) or refresh the page. If the error persists, -try clearing your browser cache and cookies. If the error still persists, please [contact the Prosopo support team](https://discord.com/invite/3nMYAHecZT). +### What does `No session found` mean? +The challenge session expired or had already been used. The widget resets itself after about 10 seconds, or you can +refresh the page. See [No session found](/en/basics/error-reference#no-session-found). ### What does `Error parsing captcha` mean? -This error will occur if incorrect data has been sent with the captcha response. To resolve this error, ensure that the -data sent with the captcha response is correct. - - - +Prosopo received a request from the widget it could not read, usually from a stale or modified copy of the Procaptcha +bundle. Hard-refresh and make sure you are loading the official bundle. +See [Error parsing captcha](/en/basics/error-reference#error-parsing-captcha). +### The widget doesn't appear at all, and there is no error message. +Some failures are written only to the browser console rather than being displayed. Open developer tools and check the +console — see [Errors that never reach the visitor](/en/basics/error-reference#errors-that-never-reach-the-visitor). diff --git a/src/i18n/en/nav.ts b/src/i18n/en/nav.ts index 1ae5b5b1f80b6..0b4937f1cc63c 100644 --- a/src/i18n/en/nav.ts +++ b/src/i18n/en/nav.ts @@ -55,6 +55,11 @@ export default [ slug: 'basics/faq', key: 'basics/faq', }, + { + text: 'Error Reference', + slug: 'basics/error-reference', + key: 'basics/error-reference', + }, {text: 'Advanced Usage', header: true, type: 'learn', key: 'advanced'}, { text: 'Context Awareness',