Skip to content

DEA SDK for Web

Detect whether a browser session comes from a real person. The SDK observes pointer, wheel, keyboard and device-motion input on the page and scores the session in the browser.

On this page: Prerequisites · Install · Initialize the SDK · Use the classification · Verify your setup · Before you release · Next steps

Prerequisites

  • An appId and appKey for this app — see Accounts and keys
  • A page served over HTTPS, or from localhost during development. The SDK needs a secure context: on any other page the browser does not provide crypto.randomUUID(), and init throws.
  • Chrome or Edge 96, Firefox 95, Safari 15.4 (iOS 15.4) or later, with WebAssembly enabled. These are the first versions that provide both crypto.randomUUID(), which the SDK calls when it starts, and the WebAssembly features its scoring engine uses.
  • A bundler or other tool that loads ES modules (Vite, webpack, Rollup, esbuild). The package is published as ES modules only.

Install

Note: @dea/sdk is installed from DEA's release URL, not from the npm registry. The URL names the release; to upgrade, install the URL of the new release. The @dea/base package it depends on comes from the same release and is installed with it.

npm

npm install https://sdk.dep-protocol.com/0.19.0/web/sdk/dea-sdk-0.19.0.tgz

yarn

yarn add https://sdk.dep-protocol.com/0.19.0/web/sdk/dea-sdk-0.19.0.tgz

pnpm

pnpm add https://sdk.dep-protocol.com/0.19.0/web/sdk/dea-sdk-0.19.0.tgz

Note: pnpm 11 stops this install with ERR_PNPM_EXOTIC_SUBDEP, because @dea/sdk depends on @dea/base by URL. Add this line to the pnpm-workspace.yaml at the root of your project (create the file if it does not exist), then run the install again:

blockExoticSubdeps: false

Content Security Policy

If your page sends a Content Security Policy, it must allow the following, or the SDK cannot load its scoring engine or reach DEA:

Directive Allow Why
script-src 'wasm-unsafe-eval' The SDK compiles its WebAssembly scoring engine in the page
connect-src data: The engine is embedded in the package's JavaScript and loaded from a data: URL. If you set coreUrl, allow that URL instead
connect-src https://sdk.dep-protocol.com Updates of the scoring model. Not needed with modelUpdates: false
connect-src https://poh-api.dep-protocol.com attest() and ad proofs

For example:

Content-Security-Policy: script-src 'self' 'wasm-unsafe-eval'; connect-src 'self' data: https://sdk.dep-protocol.com https://poh-api.dep-protocol.com

The package loads part of its own code with a dynamic import(). Your bundler emits those chunks with the rest of your scripts, so the script-src that allows your bundle allows them too.

Initialize the SDK

Initialize once, as early as possible in page load, so that capture covers the whole session.

import { init } from '@dea/sdk';

const dea = init({
  appId: 'YOUR_APP_ID',
  appKey: 'YOUR_APP_KEY',
});
  • appId and appKey are the pair DEA issued for this app. Neither is a secret: both ship in your page. Scoring works without appKey, but on a production appId without it, attest() answers 'failed' and no ad proof is signed or sent. See Accounts and keys.
  • init is safe to call more than once. A repeat call returns the running instance and keeps its session; the options of the repeat call are ignored.
  • If the scoring engine cannot load, init still returns and the SDK keeps running without a score: the classification stays 'insufficient'. It reports why on dea.error once dea.ready() has resolved.
  • Capture starts immediately. There is nothing to wrap and nothing to register. To hold capture back until the user agrees, see User Consent.
  • The SDK works out whether the page runs on a desktop or a mobile browser. To choose yourself, see profile.

Anywhere else in your code, get the running instance with DeaSdk.current:

import { DeaSdk } from '@dea/sdk';

const dea = DeaSdk.current; // null before init

Use the classification

Read the classification at the moment you make a decision. The read is synchronous and does not wait for the network.

import { DeaSdk } from '@dea/sdk';

async function onSignUp(form: SignUpForm) {
  const result = DeaSdk.current?.getClassification().result ?? 'insufficient';
  if (result === 'human') {
    await submitSignUp(form);
  } else {
    showChallenge(); // 'bot', 'undetermined' or 'insufficient': a captcha, a delay, a manual review
  }
}

SignUpForm, submitSignUp and showChallenge stand for your own code. How the score and the thresholds are produced is explained in How scoring works.

Verify your setup

  1. Check that the SDK loaded. In a page that has called init:

    import { DeaSdk } from '@dea/sdk';
    
    const dea = DeaSdk.current!;
    await dea.ready();
    console.log(dea.error);            // null: the scoring engine loaded
    console.log(dea.getSessionInfo()); // { session: '…', device: { … }, identity: { … }, motion: 'off', sdk: { version: '0.19.0', core: '…' } }
    

    If dea.error is not null, see Troubleshooting.

  2. Interact with the page — move the pointer, click, scroll, type — and read the classification again:

    console.log(dea.getClassification());
    // { result: 'insufficient', value: null, actions: 6, botThreshold: …, humanThreshold: …, modelVersion: … }
    

    Each tap, drag, scroll or run of key presses is an action. actions counts the ones the score is based on, and result stays 'insufficient' until the session is sufficient: until there are as many as the model asks for. With the built-in model, that is 20 in a desktop browser, from at least two kinds of input (pointer, scroll, keyboard) with at least three each, and 8 in a browser on a phone or tablet. See Evidence.

  3. To watch the SDK work while you integrate, install the staging package in place of the production one. It is the same SDK with its log switched on, written to the browser console:

    npm install https://sdk.dep-protocol.com/0.19.0/staging/web/sdk/dea-sdk-0.19.0.tgz
    

    Reload the page. On a first visit the console shows:

    dea 2026-10-16T01:39:29.699Z INFO  sdk.started                    ok      session.id=none account=production | SDK started on a production account
    dea 2026-10-16T01:39:29.731Z INFO  model.installed                ok      session.id=ee0962fd-… model.version=0 model.source=embedded model.theta_bot=… | Model 0 installed from embedded
    dea 2026-10-16T01:39:29.731Z INFO  sdk.ready                      ok      session.id=ee0962fd-… core=web-desktop profile=web-desktop | SDK ready: core web-desktop, profile web-desktop
    

    If you see sdk.core_failed instead, see Troubleshooting.

Warning: The staging package downloads its scoring models from DEA's staging channel, so its classification can differ from production's. Install the production package again before you release. The production package writes no log at all.

Before you release

  • [ ] The production package is installed: its URL has no /staging/ in it
  • [ ] init gets the appId and appKey DEA issued for this app — see Accounts and keys
  • [ ] The page is served over HTTPS
  • [ ] Your Content Security Policy allows the SDK — see Content Security Policy
  • [ ] The classification is read at the decision point, with a fallback for 'bot', 'undetermined' and 'insufficient' — see Human Scoring
  • [ ] Capture is paused on payment fields and any screen your privacy policy excludes — see Sensitive Screens
  • [ ] reset() is called on logout — see Sessions
  • [ ] Consent is asked for where your users need it — see User Consent
  • [ ] The cross-platform checklist is done — see Going to production

Next steps