Skip to main content

Bot Protection

Call the check-request API from your server or CDN to get allow, block, or challenge for each request. You can start with a minimal body (ip, trustedId, requestedPath) and optionally add headers and cookies for stronger detection.


Quickstart: call the endpoint (minimal body)

Call POST /api/v1/check-request with your secret in the Authorization header and a JSON body with:

  • ip (required) — client IP (e.g. from x-forwarded-for or your connection).
  • trustedId (optional) — session/visitor ID from the trusted_id cookie or a previous API response.
  • requestedPath (optional) — path the user requested (e.g. / or /page?p=1), for analytics.

On success the API returns a decision (allow, challenge, or block). On timeout or error, treat as allow (fail-open).

Example: minimal request (Node.js)

const API = 'https://api.trustedaccounts.org/api/v1/check-request';

const ip = req.ip || req.headers['x-forwarded-for'] || '';
const trustedId = req.cookies?.trusted_id ?? '';
const requestedPath = req.originalUrl || '/';

const checkRequestPayload = { ip, requestedPath };
if (trustedId) checkRequestPayload.trustedId = trustedId;

let checkResponse = { decision: 'allow' };
try {
const controller = new AbortController();
setTimeout(() => controller.abort(), 400);

const apiRes = await fetch(API, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_SECRET_KEY' },
body: JSON.stringify(checkRequestPayload),
signal: controller.signal,
});

const setCookie = apiRes.headers.get('set-cookie');
if (setCookie) res.setHeader('Set-Cookie', setCookie);

checkResponse = await apiRes.json();
} catch (_) {
// Timeout or error: keep default allow
}

Handle the response (allow, challenge, block)

DecisionAction
allowContinue to the requested page (e.g. call next() or serve the page).
challengeRedirect the user to our hosted challenge page; after completion they return to your site.
blockRedirect the user to our hosted blocked page.

For challenge and block, build the redirect URL yourself and pass these query params:

  • trusted_id — use the trusted_id from the visitor’s cookie (see Step 1; if the API sent Set-Cookie, you forwarded it so the client has the cookie).
  • publishable_key — your publishable key.
  • redirect_url — full URL where to send the user after challenge (e.g. back to the page they requested).

Hosted pages

PageURLParams
Challengehttps://challenge.trustedaccounts.org/challenge.htmltrusted_id, publishable_key, redirect_url
Blockedhttps://blocked.trustedaccounts.org/blocked.htmltrusted_id, publishable_key, redirect_url

Challenge and blocked page URLs can be overridden per project in the Trusted dashboard.

Example: handling the response (Node.js)

// Your project’s publishable key; challenge and blocked pages are hosted by us
const PUBLISHABLE_KEY = process.env.PUBLISHABLE_KEY;
const CHALLENGE_URL = 'https://challenge.trustedaccounts.org/challenge.html';
const BLOCKED_URL = 'https://blocked.trustedaccounts.org/blocked.html';

// Build the full URL for our challenge or blocked page with the query params we require
function hostedPageUrl(baseUrl, trustedId, redirectUrl) {
const params = new URLSearchParams({
trusted_id: trustedId,
publishable_key: PUBLISHABLE_KEY,
redirect_url: redirectUrl,
});
return `${baseUrl}?${params.toString()}`;
}

// Use trusted_id from the cookie (you forwarded Set-Cookie in Step 1 so the client has it)
const trustedId = req.cookies?.trusted_id ?? '';
// redirect_url: after the user completes the challenge, where they go — usually the page they requested or want to visit
// Example (replace with your domain and the path the user requested, e.g. from req.originalUrl):
const redirectUrl = 'https://your-domain.com/products';

if (checkResponse.decision === 'block') {
return res.redirect(302, hostedPageUrl(BLOCKED_URL, trustedId, redirectUrl));
}
if (checkResponse.decision === 'challenge') {
return res.redirect(302, hostedPageUrl(CHALLENGE_URL, trustedId, redirectUrl));
}
// allow: no redirect, just continue to the page they requested
next();

Extra security: send headers and cookies

For stronger detection you can send headers and cookies in the same body. You must exclude sensitive data: do not send authorization, cookie (as a header), proxy-authorization, or proxy-authenticate. We strip those server-side if present. For security, do not send cookie values — only cookie names.

  • headers — Optional object of header names (lowercase) to string values. Include e.g. user-agent, referer; we may use others for current or future checks.
  • cookies — Optional list of cookie names only (no values). E.g. ["trusted_id"] to indicate the visitor has that cookie. Send the actual trusted_id value via the top-level trustedId field.

Example: body with headers and cookies (Node.js)

const ip = req.ip || req.headers['x-forwarded-for'] || '';
const trustedId = req.cookies?.trusted_id ?? '';
const requestedPath = req.originalUrl || '/';

// Exclude sensitive headers
const SENSITIVE = new Set(['authorization', 'cookie', 'proxy-authorization', 'proxy-authenticate']);
const headers = {};
for (const [key, value] of Object.entries(req.headers)) {
if (value == null) continue;
const name = key.toLowerCase();
if (SENSITIVE.has(name)) continue;
headers[name] = Array.isArray(value) ? value.join(', ') : value;
}

const checkRequestPayload = { ip, requestedPath, headers };
if (trustedId) checkRequestPayload.trustedId = trustedId;
// Optional: send cookie names only (never send values). Derive from your request.
if (req.cookies && typeof req.cookies === 'object') {
checkRequestPayload.cookies = Object.keys(req.cookies);
} else if (req.headers?.cookie) {
const cookieHeader = Array.isArray(req.headers.cookie) ? req.headers.cookie[0] : req.headers.cookie;
checkRequestPayload.cookies = cookieHeader.split(';').map(s => s.trim().split('=')[0]).filter(Boolean);
}

const apiRes = await fetch(API, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_SECRET_KEY' },
body: JSON.stringify(checkRequestPayload),
signal: controller.signal,
});
// cookies is always an array of names, e.g. ["trusted_id", "session_id"]; the trusted_id value is sent in trustedId.

Privacy: The trusted_id cookie is for bot protection only (no PII); include it in your cookie notice.