Browser SDK troubleshooting
Use this page when the collector does not start, does not collect, or collects less than you expect. Every symptom below comes from an error body, a result code, an event or a console message that the collector produces. Start with the console checks, then find your symptom in the tables.
What it is
Availability: Evaluation access. Availability depends on your plan, role and the modules enabled for your organisation.
The core script fails open. A problem in the collector does not block your page, and most failures show up as a missing event, a reason and code in a result, a noxtica:error event, or an HTTP error on a /client/* call. This page maps those signals to causes. Concepts are on Install and Browser Runtime; the full reference is on the other pages of this section.
Prerequisites
- A browser with DevTools (Console and Network).
- The page that shows the problem, served from the origin registered for the Site Key.
- Your Site Key. It is public. Never post a Server API key (
sk_…), a session token or a cookie value in a ticket. - For consent questions, the consent mode of the domain: Backoffice → Integrations & API → Script & Consent → Consent & extensions.
Steps
1. Read the loader state
Run this in the console of the affected page:
({
version: window.noxtica && window.noxtica.v, // loader version, set by the initial core script
loader: typeof window.NoxticaCollector, // 'object' when a core script ran
client: typeof window.noxticaClient, // 'object' when a data-auto-init tag bound
consent: window.noxticaClient && window.noxticaClient.getConsent(),
extensions: window.noxticaClient && window.noxticaClient.getExtensionsState(), // 'not-loaded' | 'attached' | 'built-in'
lastResult: window.noxticaResult,
lastError: window.noxticaLastError, // { source, message, time }
logLevel: window.NoxticaCollector && window.NoxticaCollector.getLogLevel(),
});
To see more, set the log level to debug with data-log-level="debug" on the tag and reload. The loader is silent by default. See Script attributes and client options.
2. Check the Network tab
Filter by your collector host. A working page shows the core script and POST /client/token with status 200. After consent in a gated mode it also shows the extensions script, engine files and POST /client/submit. An error body from the collector carries a requestId; keep it for support.
3. Check consent and the extensions
Read getConsent(): mode, modeResolved and the four categories. Then call await window.noxticaClient.loadExtensions() and read ok, reason and code. The tables below explain each value.
4. Check the policy
Open the console on a page with the policy in force and look for violations that name a Noxtica host. See Content Security Policy, hosts and first-party relay.
5. Collect what support needs
Send: your Site Key, the page URL without query strings, the loader version (window.noxtica.v), the output of step 1, the failing request with its status and requestId, and the time. Contact your account team or use Contact. Platform incidents are listed on status.noxtica.com.
6. Check the browser
The collector needs WebAssembly and blob: workers for its engines. GPU attestation also needs WebGPU: without it the loader logs WebGPU not available and skips that step. The Web Locks API is optional; a browser without it falls back to a localStorage lock for the cross-tab check. A privacy mode, an extension or a network rule that blocks cross-origin requests, storage, workers or WebAssembly reduces the evidence or stops collection, and the page keeps working.
Headless and automated browsers are scored as bots, and your CDN may challenge them. Do not compare risk scores from headless runs. Test on a lab page, as described in Release checks, testing and versions.
Noxtica does not publish a verified minimum browser version list in this documentation. Test the browsers and privacy modes your own application supports.
Verify it works
After a fix, reload the page with a clean profile and check:
typeof window.noxticaClientis'object'andwindow.noxtica.vholds a version.POST /client/tokenanswers200.window.noxticaLastErrorisundefined.- In a gated mode,
getConsent().modeResolvedistrue; after consentgetExtensionsState()is'attached'. - Exactly one
noxtica:collectedevent fires for the page.
Troubleshooting
The script does not start
| Symptom | Cause | Fix |
|---|---|---|
window.noxticaClient undefined and no noxtica:* events | The tag lacks data-auto-init or data-site-key, or the src file name has neither noxtica-collector nor /noxtica.js | Add the attributes and keep the file name. A tag without a Site Key is skipped silently. |
window.NoxticaCollector undefined | The core script did not load: blocked by CSP or a network rule, a 404, or an integrity failure | Read the failed request in Network and the console. See the CSP page. |
| Pinned tag blocked with an integrity error | The pin is more than three releases old, or the hash was copied from a document | Copy the tag again from Script & Consent → Snippets, or use the stable tag. |
NX001: already loaded (v…), duplicate tag v… ignored. | A second core or combined tag on the page | Remove it. The initial tag keeps running and its version is window.noxtica.v. |
window.noxtica(...) does nothing | window.noxtica is a plain object without q, or the tag lacks data-auto-init | Define the stub as a function or array. |
NoxticaCollector: siteKey is required | createClient found no Site Key | Pass siteKey or keep data-site-key on a collector tag. |
| A relay or proxy path loads the script but nothing binds | The proxied file name lost noxtica-collector | Keep the file name when you proxy the script. |
POST /client/token fails
| Status and body | Cause | Fix |
|---|---|---|
403 Origin not allowed | The request had no Origin header, so it did not come from a normal browser page | Test from a real page on the registered origin. |
403 Origin mismatch | The page origin differs from the origin registered for the Site Key | Use the key of the exact origin. Staging needs its own domain and key. |
400 Missing siteKey | The request body had no Site Key | Check the tag’s data-site-key or the siteKey option. |
401 Invalid siteKey | The Site Key is unknown or inactive | Copy the key again from Backoffice → Domains. |
403 Tenant suspended or Domain disabled | The account or the domain is not active | Contact your account team. |
429 Rate limit exceeded, with Retry-After | The tenant and client address hit the token rate limit | Wait for Retry-After. |
429 quota_exceeded with code COLLECTOR_REQUESTS_QUOTA_EXCEEDED | The monthly collector request quota is used up, when quota enforcement is enabled | Check usage in Backoffice and see Usage, quotas and metering. |
413 Payload too large or 415 Content-Type must be application/json | A custom client or proxy changed the request | Do not rewrite collector requests. |
Consent and gated modes
| Symptom | Cause | Fix |
|---|---|---|
noxtica:collected has skipped: 'consent_required' | A gated mode and deviceId not granted | Call setConsent({ deviceId: 'granted' }) after the visitor agrees. Not an error. |
getConsent().mode is not_required on an api domain | modeResolved is false: the saved mode has not arrived | Wait for noxtica:consent-changed, or declare data-consent-mode. |
setConsent throws NoxticaCollector.setConsent requires granted, denied, or { analytics, replay, deviceId, behavioral } | A boolean or another shape | Pass 'granted' or 'denied'. |
setConsent throws unknown consent category or … must be granted or denied | A wrong key or value | Use the four category names with the two strings. |
| Extensions load for visitors who declined | Not required mode with automatic loading, or a legacy script URL | See Consent modes. |
Two noxtica:collected events with different ids | Loader older than 3.8.1 | Update to the current loader; take the id from the server verify call. |
fingerprintId in the browser differs from the server | The core and the extensions mint different ids | Use the id from POST /v1/protected-actions/verify. |
Extensions: loadExtensions() results
loadExtensions() never rejects. It resolves { ok: true, loaded } or { ok: false, reason, code, … }. A later call retries after a failure.
reason | code | Cause | Fix |
|---|---|---|---|
consent_missing | consent_required | You passed { requireConsent: true } in a gated mode and no category is granted | Grant a category before you call it, or drop the option. |
consent_missing | consent_withdrawn | A queued loadExtensions was dropped because the queued consent denies all four categories (loader 3.8.1 and later) | Call loadExtensions() after a grant. |
csp_blocked | script-src-elem or script-src | An enforced CSP blocked the script | Allow the collector host in that directive. |
integrity_mismatch | sha384_mismatch | A pinned file’s bytes differ from its hash | Copy the pinned tag again. |
network | http_<status>, fetch_failed | The file returned an HTTP error or no response | Check the host, the proxy and connect-src. |
timeout | script_timeout | No load or error event within 20 seconds | Retry. Check the network path. |
already_loaded | script_present | A <script> for the extensions URL is in the page but nothing registered | Remove your own extensions tag, or fix why it did not run. |
unknown | build_mismatch | The extensions come from another build than the core | Load core and extensions from the same collector release. |
unknown | invalid_extensions, handoff_failed, not_registered | The extensions did not register or take over | Reload; report with the error text. |
unknown | script_exception, script_error | The browser rejected a file that is reachable, or the script threw | Check the console. |
unknown | no_pinned_manifest, no_document, client_destroyed | The core has no extensions manifest, there is no document, or the client was destroyed | Use a current core, call from a browser page, create a new client. |
unknown | legacy_loader | The typed wrapper normalised a boolean from a loader older than 3.8.0 | Update the loader. |
error is human text. Do not parse it. The classification is approximate, because the browser’s error event carries no cause.
Protected actions
| Symptom | Cause | Fix |
|---|---|---|
protect() resolves error: 'undeclared_protected_action' | The name is not declared for the domain | Declare it and reload. |
protect() rejects with NoxticaCollector.protect: invalid protected action name | The name does not match the action grammar | Use lowercase letters, digits, - and _, starting with a letter. |
A form posts without nox_request_id | The check exceeded the hold time or the script was blocked | Treat it as no client signal. See Protected actions. |
Verify returns 409, 404 or 422 | Replay, expired or foreign id, or an action or domain mismatch | See the status table on the protected-actions page. |
Responses and signatures
| Symptom | Cause | Fix |
|---|---|---|
Console warnings Policy signature verification failed or Result signature verification failed, or errors that mention Missing policySigned envelope or Missing resultSigned envelope | A response without its signed envelope, or whose signature does not verify. A rule or proxy that rewrites collector responses can cause it. | Stop rewriting collector responses. Keep signatureMode at require. |
noxtica:error with source Auto-init failed, Auto-check-once failed, Auto-collect failed or Deferred page check failed | The automatic step threw; message holds the cause, cut to 200 characters | Read window.noxticaLastError.message, then match it to a row above. |
Challenges and blocks
| Symptom | Cause | Fix |
|---|---|---|
noxtica:challenge with status: 'unsupported' | The browser cannot run the requested method (gpu-pow or turnstile) | Informational. The server decides what happens next. |
| A full-page overlay or a redirect | The server issued a block for the visit; noxtica:block reports overlay or redirect | Review the risk decision in Backoffice. The page cannot dismiss the overlay. |
Related
- Install and Browser Runtime: install, consent and the check list.
- Script attributes and client options: every attribute and option.
- Client API, events and the command queue: events and result shapes.
- Consent modes, GPC and Google Consent Mode: modes and categories.
- Content Security Policy, hosts and first-party relay: policy and relay setup.
- SDK Changelog: behaviour that changed between loader releases.