Skip to content
LR Defender
Book a demo

Quick start

Your first verdict in three calls: your server mints a session, the browser runs the SDK, and your server fetches the verdict. Nothing to install.

Before you start

  • An LR Defender account. Book a demo: after the call, we set up your account and email you a link to set your password. It starts with a 90-day free trial on the Pro plan's limits, with no card. When the trial ends, the dashboard locks and the SDK and the API refuse your keys until our team moves your account to a paid plan.
  • Your secret key. Sign in, then create a key under Developers, API keys in the dashboard. It starts with sk_ and belongs on your server only.
  • The origin of the page that will run the check, for example https://app.example.com. A session works only from the origin you name.

1. Add the script tag

Add one script tag to the pages where you check a visitor: sign-up, login, checkout. It loads the SDK from our script host and defines one global, LightningResearchSDK. There is nothing to install.

<!-- In the head of every page that runs a check --><script src="https://cdn.lrdefender.lightningresearch.ai/sdk/v1/lr.min.js"></script>

Using React, Vue, Angular or Next.js? The tag goes in the same place, and Frameworks shows where. If your site sends a Content-Security-Policy, allow what Content-Security-Policy lists.

2. Mint a session on your server

POST/api/collector/sessionSecret key, X-API-Key

Each time a page is about to run a check, your server asks for a session and hands its token to that page, for example from a route of your own such as POST /api/lr-session. A session is short-lived and allows a few identifications, so mint one per check.

curl -X POST https://api.lrdefender.lightningresearch.ai/api/collector/session \  -H "X-API-Key: $LR_SECRET_KEY" \  -H "Content-Type: application/json" \  -d '{"origin": "https://app.example.com"}'
originstringRequired
The origin of the page that runs the check. Without it the call returns 400 with the code origin_required.
ttlSecondsintegerOptional
How long the session lasts, from 30 to 600 seconds. Default 120.
maxUsesintegerOptional
How many identifications the session allows, from 1 to 20. Default 3.

The response carries the token for the page:

{  "tokenType": "Bearer",  "sessionToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",  "expiresAt": "2026-09-26T10:02:00.000Z",  "collectPath": "/collect/device",  "maxUses": 3,  "tenantId": "5f1c09a2b7e4d3c8a1f60b92",  "agentDetection": false}

A missing or invalid key returns 401. A 403 carries a code that says why: origin_not_allowed for an origin your account does not allow, secret_key_in_browser when a secret key is sent from a browser, or a license code when your license is not active.

3. Identify in the browser

On the page, construct the client with the session token and call identify(). It collects the signals, sends them to us, and resolves with a request ID for this identification.

// sessionToken comes from your server (step 2).const lr = new LightningResearchSDK.LightningResearch({ sessionToken }); let requestId = null;try {  const result = await lr.identify();  requestId = result.requestId ?? null;} catch {  // Network error or blocked script: requestId stays null.}// Send requestId to your server with the form. If it is null, treat the check as not run.

4. Fetch the verdict on your server

GET/api/device-id/{requestId}Secret key, X-API-Key

When the form reaches your server, fetch the verdict for its request ID with your secret key.

curl https://api.lrdefender.lightningresearch.ai/api/device-id/$REQUEST_ID \  -H "X-API-Key: $LR_SECRET_KEY"

An unknown or expired request ID returns 404 with the status not_found. Results are kept for 24 hours after the identification.

GET /api/device-id/:requestIdRecorded Sep 25, 2026
{
"requestId": "8a1f471e8ef258dc1ace08d2",
"status": "success",
"deviceId": "172a2cc7f79e51c77e5d477f",
"identification": {
"confidence": {
"score": 1,
… 2 more fields
},
… 4 more fields
},
"matchType": "alias",
"visitCount": 27,
"risk": {
"level": "low",
"recommendation": {
"action": "allow",
… 6 more fields
},
… 1 more field
},
"smartSignals": {
"botDetection": {
"isBot": false,
… 3 more fields
},
… 16 more fields
},
"ipBlocklist": {
"tor_node": false,
… 2 more fields
},
… 28 more fields
}

Hover or focus a field to read what it means.

A captured response, abridged to ten fields. Hover or focus a field to read what it means. The full response also carries browser details, IP data and each smart signal; the API reference lists the documented fields.

Act on the verdict

risk.recommendation.action is one of four values. Map each to a step in your own flow:

allow
Let the request through.
monitor
Let it through, and review the account later.
challenge
Ask for another step first, such as a code sent by email.
block
Refuse the request.
No verdict
The check did not run. Apply your own policy for unchecked requests.

risk.recommendation.reasonCodes says why, as stable keys you can log, and smartSignals.botDetection.isBot says whether the bot checks flagged the visit.

If you write rules in the dashboard, also read ruleAction: it says block, challenge or flag when one of your rules matched, and ruleResults lists the rules. Your rules never change risk.recommendation.action, so act on the stricter of the two. When your server identifies through POST /api/device-id, a matching block rule answers 403 with status blocked instead of a verdict.

Test with automation

Before you go live, drive your own sign-up page with an automated browser, then fetch the verdict for that request ID as in step 4. Playwright with its default settings is the first test to run:

// Drive your own sign-up page with Playwright's default settings.import { chromium } from "playwright"; const browser = await chromium.launch(); // headless, default settingsconst page = await browser.newPage();await page.goto("https://staging.example.com/sign-up");await page.fill("#email", "test@example.com");await page.click("button[type=submit]");await page.waitForTimeout(3000);await browser.close();// Then fetch the verdict for that request ID on your server (step 4).

This is what we recorded on Sep 25, 2026, when Chrome, launched headless by Playwright with its default settings, ran the same identification against our own test page:

Headless Chrome, Playwright defaultsRecorded Sep 25, 2026
{
"smartSignals": {
"botDetection": {
"isBot": true,
"botKind": "automation_tool",
… 2 more fields
},
… 16 more fields
},
"risk": {
"level": "high",
"recommendation": {
"action": "challenge",
"reasonCodes": ["behavior_bot_high","factor_behavioral_risk","factor_bot_de…,
… 5 more fields
},
… 1 more field
},
… 36 more fields
}

Hover or focus a field to read what it means.

A default automated browser is the easy case. Detection for AI agents driving a real browser is on by default, and you can switch it off for your account under Detection settings in the dashboard. Talk to an engineer if you want help reading its first results.

Next steps

  • Frameworks: the script tag and the check in React, Vue, Angular and Next.js.
  • Server API: device lookups and network lookups from your server.
  • Webhooks: signed events sent to your endpoint.
  • API reference: every endpoint in the OpenAPI spec.

Get a verdict in your own app.

After a demo call, we set up your account and email you a link to set your password. It starts with a 90-day free trial on the Pro plan's limits, with no card.