JavaScript SDK
Use @requestguard/js for fraud decisioning, signup protection, checkout risk scoring, CAPTCHA, and protected links.
Install the SDK:
bun add @requestguard/js
Create a server-side client with an active workspace API key. Every intelligence method, including Free geolocation and vulnerabilities, requires this key:
import RequestGuard from "@requestguard/js";
const rg = RequestGuard({
apiKey: "rg_sk_live_..."
});
Plans, Quotas and Errors
Free includes 1,000 shared geolocation/vulnerability units per UTC calendar month and one API key. Other intelligence methods require Suite or Lookups. Paid Email alone does not unlock those methods. Bulk requires Suite Business, Suite Agency or Lookups Growth; webhooks require Suite Agency or Lookups Growth. Compatible plans use the highest allowance, never a sum.
REST failures include 401 UNAUTHORIZED, 402 QUOTA_EXCEEDED, 403 CAPABILITY_REQUIRED, 403 BULK_LOOKUPS_REQUIRED, 403 API_KEY_PAUSED and 429 RATE_LIMITED. Do not retry a capability denial or an exhausted monthly allowance as a transient failure. An admitted retry consumes another unit. See Authorization for the complete capability and quota contract.
Signup Protection
assess() requires any Suite or Lookups plan and consumes one workspace lookup unit. It returns a decision with supporting evidence.
const assessment = await rg.assess({
ip: request.headers.get("cf-connecting-ip"),
email: form.email,
userAgent: request.headers.get("user-agent"),
event: "signup",
sessionId: session.id,
metadata: {
plan: "free",
campaign: "paid_ad"
}
});
if (assessment.decision === "block") {
return new Response("Signup blocked", { status: 403 });
}
if (assessment.decision === "challenge") {
return requireCaptcha();
}
Express Middleware
export function requestGuardSignup(rg) {
return async (req, res, next) => {
const assessment = await rg.assess({
ip: req.ip,
email: req.body.email,
userAgent: req.get("user-agent"),
event: "signup"
});
if (assessment.decision === "block") {
return res.status(403).json({ error: "high_risk_signup", assessment });
}
res.locals.requestGuard = assessment;
return next();
};
}
Hono Middleware
app.use("/signup", async (c, next) => {
const assessment = await rg.assess({
ip: c.req.header("cf-connecting-ip"),
email: (await c.req.json()).email,
userAgent: c.req.header("user-agent"),
event: "signup"
});
if (assessment.decision === "block") {
return c.json({ error: "high_risk_signup", assessment }, 403);
}
c.set("requestGuard", assessment);
return next();
});
Next.js Route Handler
export async function POST(request) {
const body = await request.json();
const assessment = await rg.assess({
ip: request.headers.get("x-forwarded-for")?.split(",")[0],
email: body.email,
userAgent: request.headers.get("user-agent"),
event: "signup"
});
if (assessment.decision === "block") {
return Response.json({ error: "Blocked" }, { status: 403 });
}
return Response.json({ ok: true, assessment });
}
Stripe Checkout Fraud
const assessment = await rg.assess({
ip: request.ip,
email: checkout.customer_email,
event: "checkout",
billingCountry: checkout.billing_address_collection?.country,
metadata: {
amount: checkout.amount_total,
currency: checkout.currency
}
});
if (assessment.decision === "review" || assessment.decision === "block") {
// delay fulfillment or ask for stronger verification
}
Python
The repository also includes a small Python SDK in packages/python-sdk for server-side integrations.
from requestguard import RequestGuard
rg = RequestGuard(api_key="rg_sk_live_...")
assessment = rg.assess(
ip=request.remote_addr,
email=form["email"],
user_agent=request.headers.get("user-agent"),
event="signup",
)
if assessment["decision"] == "block":
abort(403)
Clerk / Supabase / Auth0
Call assess() before account creation or from the provider webhook. Store assessment.requestId on the user record so support and security teams can search it later in the dashboard.
const assessment = await rg.assess({
ip,
email,
event: "signup",
userId: externalUserId,
metadata: { identity_service: "auth0" }
});
Protected Links
Use rg.createLink() when your app needs to create bot-protected short links dynamically. RequestGuard reuses an existing active link for the same destination when the link has no expiry and no password.
API key is optional for createLink(). Omit apiKey for anonymous go.requestguard.com link creation, or include one when you want account-scoped tracking and active-link reuse. Go uses separate creation rate limits and consumes no lookup units.
const go = RequestGuard({ endpoint: "https://api.requestguard.com/v1" });
const link = await go.createLink({
targetUrl: "https://example.com/private-video"
});
console.log(link.protectedUrl);
console.log(link.reused);
Protected links can also wrap iframe content, such as private video embeds:
<iframe
src="https://go.requestguard.com/a1c2d3rs/"
loading="lazy"
referrerpolicy="strict-origin-when-cross-origin"
></iframe>
Lower-Level Helpers
Use the authenticated rg client created above. Geolocation is included in Free; the other intelligence helpers below require Suite or Lookups.
const connection = await rg.connection({ ip: "8.8.8.8" });
const geo = await rg.geolocation({ ip: "1.1.1.1" });
const email = await rg.email("user@tempmail.test");
const domain = await rg.domain("example.com");
const subdomains = await rg.subdomains("api.example.com", { limit: 100, offset: 0 });
const infrastructure = await rg.infrastructure("api.example.com");
const whois = await rg.whois("example.com");
const isVpn = await rg.isVPN("185.220.101.1");
const isProxy = await rg.isProxy("185.220.101.1");
const isTor = await rg.isTor("185.220.101.1");
const emailRisk = await rg.emailRisk("user@tempmail.test");
const userRisk = await rg.userRisk({ userId: "user_123", event: "signup" });
Vulnerability Evidence
Vulnerability methods require an active workspace API key and are included in Free. Each request consumes one unit from the shared monthly lookup allowance. Package/version evidence and CISA KEV catalog evidence remain separate from fraud decisions.
const vulnerabilityRg = RequestGuard({ apiKey: "rg_sk_live_..." });
const report = await vulnerabilityRg.packageVulnerabilities("npm", "lodash", {
version: "4.17.20",
limit: 100,
offset: 0
});
const cve = await vulnerabilityRg.cve("CVE-2021-44228");
const kev = await vulnerabilityRg.knownExploitedVulnerabilities({
vendor: "Apache",
ransomware: "known",
limit: 25
});
Supported package ecosystems are npm, composer, pypi, maven, and go.
Website Security
These methods require Suite or Lookups and each consumes one lookup unit. Saved ongoing website monitoring separately requires a Suite plan. The website-security methods use the separate higher-is-better configuration score. They do not change rg.domain() or its threat score.
const report = await rg.websiteScan("www.example.com");
const latest = await rg.websiteSecurity("example.com");
const board = await rg.websiteLeaderboard({
view: "top",
limit: 50,
offset: 0
});
console.log(report.apex_domain, report.score.value, report.scan.checked_at);
websiteScan() reuses a complete report for five minutes and can serve it as marked stale data for up to 24 hours when a new probe fails. A report with an unavailable required check has score.value: null and is excluded from the Top and Improved since previous views.
CAPTCHA Fallback
const assessment = await rg.assess({ ip, email, event: "signup" });
if (assessment.decision === "challenge") {
RequestGuard.captcha({
el: ".rg-captcha",
onVerify: (result) => {
document.querySelector("button[type=submit]").disabled = !result.success;
}
});
}
<div class="rg-captcha"></div>
Custom API Endpoint
Use endpoint for self-hosted or staging API deployments:
const rg = RequestGuard({
apiKey: "rg_sk_test_...",
endpoint: "https://api.example.com/v1"
});