// DEVELOPER API

SafeBrowz Detection API

Phishing and wallet drainer detection for any URL. Pay per request with USDC on Solana or Base via x402 - no signup required. High-volume integrators get a Bearer key and a flat monthly subscription.

New here? Read the deep dive on the x402 detection API.

What is the SafeBrowz Detection API?

SafeBrowz provides a real-time scam and phishing detection API. Send any URL to a single endpoint and get back a verdict (safe, caution, or danger), the impersonated brand if any, a trust score, and 22 threat signals, typically in 50 to 150 ms. It runs the same 3-layer engine (local rules, threat APIs, and AI page analysis) as the SafeBrowz browser extension. Pay 0.01 USD per call with no signup, or use a flat monthly plan from 20 USD per month for steady, high-volume server-side use such as link shorteners and marketplaces. You can also try the detection free in your browser or license it for your whole team.

// FOR AI AGENTS

Drop-in agent skill

Building a Claude Agent, ChatGPT Custom GPT, Cursor rule, or any LLM-driven app? Paste our skill file into your agent's rules and it will know when and how to call the API.

/skill

Agent Skill (markdown)

Complete skill definition with triggers, payment flow, signal interpretation, code examples. Ready to paste into any agent framework.

Download skill.md
/openapi

OpenAPI 3.1 Spec

Machine-readable endpoint schema. Use with ChatGPT Actions, Postman, Insomnia, or any SDK generator.

View openapi.json
/llms

LLM-friendly Docs

Full plain-text reference optimized for AI crawlers and agent context windows. Includes citation guidance.

View api-llms.txt

Plugin manifest at /.well-known/ai-plugin.json

// PRICING

Simple pricing

$0.01

Per request

Pay in USDC on Solana or Base per request, no signup or commitment. For steady, high-volume use, a flat plan starts at $20/month with a Bearer key and an included request allowance.

Full scan

Extension parity

Every signal the SafeBrowz browser extension detects - credential phishing, pastejacking, ClickFix, wallet drainers, brand impersonation, and 18 more - is returned by the API. No URL-only shortcut.

550+

Brands tracked

Covers wallets (MetaMask, Phantom, Ledger, Trezor), exchanges (Binance, Coinbase, OKX), payment services (PayPal, Venmo, Stripe), and major global consumer brands.

// TRY IT LIVE

Run the full x402 flow in your browser

Connect any wallet, paste a URL, click test. Pay 0.01 USDC on Solana or Base. Works with any SPL or EVM wallet. Solana wallet needs a small SOL balance for the network fee.

Pick a chain below - cost stays the same.

Need 0.01 USDC + a tiny bit of SOL for the network fee on Solana, or 0.01 USDC + ETH gas on Base. No refunds - payment is onchain.

// QUICKSTART

Or curl it in 30 seconds

Every request requires an x402 payment. First call returns 402 with payment instructions. Pay, then retry with the transaction signature.

Step 1 - Get a 402 nonce

curl -s -X POST https://api.safebrowz.com/v1/detect \
  -H "Content-Type: application/json" \
  -d '{"url":"https://app.trezor-io.us.com/"}'

Response (402)

Pick any option inside payment or payment.alternatives. The primary entry is Solana USDC; the alternative is Base USDC.

{
  "status": 402,
  "error": "payment_required",
  "payment": {
    "amount": "0.01",
    "token": "USDC",
    "token_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "chain": "solana",
    "recipient": "FLQyppmJYbvQvEPAB4Mv8ZGmxkSXmXUwMACeJ79kdozW",
    "nonce": "ed548e77-719f-4f13-9f01-32dc8ed4e213",
    "memo_format": "safebrowz:ed548e77-719f-4f13-9f01-32dc8ed4e213",
    "alternatives": [
      { "token": "USDC", "amount": "0.01",   "chain": "base",   "chain_id": 8453,
        "token_contract": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
        "recipient": "0xf3bc3a04646F1D721992AeDC07c98FC52FdFC358",
        "nonce_binding": "eip191",
        "sign_message": "safebrowz:ed548e77-719f-4f13-9f01-32dc8ed4e213" }
    ]
  }
}

Step 2a - Pay on Solana

Transfer 0.01 USDC to the recipient with memo safebrowz:<nonce>. Any Solana wallet or the spl-token CLI works. Nonces expire in 10 minutes.

spl-token transfer EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v 0.01 \
  FLQyppmJYbvQvEPAB4Mv8ZGmxkSXmXUwMACeJ79kdozW \
  --fund-recipient \
  --with-memo "safebrowz:ed548e77-719f-4f13-9f01-32dc8ed4e213"

Step 2b - Pay on Base (EVM wallets)

Send a standard USDC ERC-20 transfer on Base to the recipient, then sign the nonce message off-chain. Base lacks a native memo field, so nonce binding uses EIP-191 personal_sign of safebrowz:<nonce>. The signature must recover to the wallet that paid.

// viem / ethers pseudocode
const txHash = await wallet.writeContract({
  address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC on Base
  abi: erc20Abi, functionName: "transfer",
  args: [ "0xf3bc3a04646F1D721992AeDC07c98FC52FdFC358", 10000n ], // 0.01 USDC (6 dec)
});
const walletSig = await wallet.signMessage({
  message: "safebrowz:ed548e77-719f-4f13-9f01-32dc8ed4e213",
});

Step 3 - Retry with the proof

For Solana, send the tx signature only. For Base, also send the EIP-191 wallet signature and set X-402-Chain: base.

# Solana
curl -s -X POST https://api.safebrowz.com/v1/detect \
  -H "Content-Type: application/json" \
  -H "X-402-Signature: <your_tx_signature>" \
  -H "X-402-Nonce: ed548e77-719f-4f13-9f01-32dc8ed4e213" \
  -d '{"url":"https://app.trezor-io.us.com/"}'

# Base
curl -s -X POST https://api.safebrowz.com/v1/detect \
  -H "Content-Type: application/json" \
  -H "X-402-Chain: base" \
  -H "X-402-Signature: <tx_hash>" \
  -H "X-402-Wallet-Sig: <eip191_signature>" \
  -H "X-402-Nonce: ed548e77-719f-4f13-9f01-32dc8ed4e213" \
  -d '{"url":"https://app.trezor-io.us.com/"}'

Response (200)

{
  "verdict": "danger",
  "trust_score": 5,
  "brand": "Ledger",
  "confidence": 0.95,
  "reason": "Fake Ledger Live login page - potential phishing and crypto scam",
  "threat_types": ["brand_impersonation", "crypto_scam", "credential_phishing"],
  "signals": {
    "brand_impersonation": true,
    "credential_phishing": true,
    "crypto_scam": true,
    "no_contact_info": true,
    "domain_mismatch": true,
    "wallet_drainer": false,
    "seed_phrase_phishing": false,
    "fake_captcha": false,
    "pastejacking": false,
    "tech_support_scam": false
    // ...remaining signals (all booleans) omitted for brevity
  },
  "details": {
    "matched_brand": "Ledger",
    "official_domain": "ledger.com",
    "domain_matches_brand": false,
    "target_country": "Global",
    "page_language": "English"
  }
}

trust_score is a simple 0-100 trustworthiness score (100 = safe, 0 = scam). confidence is how sure we are of the verdict itself - for a danger verdict, 0.95 means "we are 95% sure this is a scam," not "95% fake."

// INTEGRATE

Full programmatic clients

Copy-paste one of these, plug in a wallet, you are done. Each example handles the full x402 flow end-to-end: initial call, parse 402 challenge, pay onchain, retry with X-PAYMENT header. Mix and match languages - the API is identical regardless of which client calls it.

TypeScript + viem (Base)

A ~45-line client that covers the full round trip on Base mainnet. Uses viem for USDC transfer + EIP-191 nonce sig.

import { createWalletClient, http, parseUnits, erc20Abi } from "viem";
import { base } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";

const USDC_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
const URL = "https://api.safebrowz.com/v1/detect";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const wallet  = createWalletClient({ account, chain: base, transport: http() });

export async function detect(target: string) {
  // 1. First call - expect 402
  const first = await fetch(URL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ url: target }),
  });
  if (first.status !== 402) return first.json();
  const challenge = await first.json();
  const baseEntry = challenge.accepts.find((a: any) => a.network === "base");

  // 2. Pay USDC onchain to the configured receiver
  const txHash = await wallet.writeContract({
    address: USDC_BASE, abi: erc20Abi, functionName: "transfer",
    args: [baseEntry.payTo, parseUnits("0.01", 6)],
  });

  // 3. Sign the off-chain nonce binding (EIP-191 personal_sign)
  const walletSig = await wallet.signMessage({
    message: baseEntry.extra.sign_message_template,
  });

  // 4. Retry with the spec-compliant X-PAYMENT header
  const xPayment = Buffer.from(JSON.stringify({
    x402Version: 1, scheme: "exact", network: "base",
    payload: {
      txHash, walletSig,
      nonce: baseEntry.extra.sign_message_template.split(":")[1],
    },
  })).toString("base64");

  const verdict = await fetch(URL, {
    method: "POST",
    headers: { "Content-Type": "application/json", "X-PAYMENT": xPayment },
    body: JSON.stringify({ url: target }),
  });
  return verdict.json();
}

Python + solana-py (Solana)

Same flow on Solana. Uses solders for keypair + transaction construction and the SPL-memo instruction for nonce binding.

import base64, json, httpx, os
from solana.rpc.api import Client
from solders.keypair import Keypair
from solders.pubkey import Pubkey

USDC_MINT = Pubkey.from_string("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v")
rpc = Client("https://api.mainnet-beta.solana.com")
kp  = Keypair.from_base58_string(os.environ["SOLANA_SECRET"])

def detect(target: str) -> dict:
    # 1. Challenge
    r = httpx.post("https://api.safebrowz.com/v1/detect",
                   json={"url": target})
    if r.status_code != 402:
        return r.json()
    sol_entry = next(a for a in r.json()["accepts"] if a["network"] == "solana")

    # 2. Build USDC transferChecked + spl-memo binding the nonce
    memo = sol_entry["extra"]["memo_template"]   # "safebrowz:<nonce>"
    tx   = build_usdc_transfer_with_memo(
        payer=kp.pubkey(),
        receiver=Pubkey.from_string(sol_entry["payTo"]),
        amount_atomic=int(sol_entry["maxAmountRequired"]),
        memo_text=memo,
    )
    tx.sign([kp], rpc.get_latest_blockhash().value.blockhash)
    tx_sig = rpc.send_transaction(tx).value

    # 3. Retry with X-PAYMENT
    x_payment = base64.b64encode(json.dumps({
        "x402Version": 1, "scheme": "exact", "network": "solana",
        "payload": {"txSignature": str(tx_sig), "nonce": memo.split(":")[1]},
    }).encode()).decode()

    return httpx.post(
        "https://api.safebrowz.com/v1/detect",
        headers={"X-PAYMENT": x_payment},
        json={"url": target},
    ).json()

Zero-config - agentcash CLI

If you do not want to roll your own payment flow, agentcash ships the whole x402 dance. It detects 402, signs and broadcasts the payment, retries with the spec-compliant header, and prints the verdict. One line:

npx agentcash fetch https://api.safebrowz.com/v1/detect \
  --body '{"url":"https://trezor-support.com"}' \
  --network solana

Works on both --network solana and --network eip155:8453. Uses an agentcash-managed wallet - top it up with USDC and it just works.

Agent frameworks - Claude, GPT, LangChain, MCP

Every major agent framework can load our published skill file and use the detection API as a tool without any manual integration code:

# Claude Code / Claude Desktop
#   - Save /safebrowz-api.skill.md locally
#   - Add to your ~/.claude/skills/ directory
#   - Claude loads it automatically

# MCP server config (Claude Desktop, etc.)
#   - Point at the OpenAPI spec: https://api.safebrowz.com/v1/openapi.json
#   - MCP auto-generates a detect() tool

# LangChain
from langchain.tools import OpenAPIToolkit
from langchain.utilities.openapi import OpenAPISpec
spec = OpenAPISpec.from_url("https://api.safebrowz.com/v1/openapi.json")
toolkit = OpenAPIToolkit.from_llm_and_spec(llm, spec)

Enterprise Bearer auth (bypass x402)

High-volume integrators - wallet apps and AI platforms with millions of end users - can request a long-lived Bearer key. No per-call signing; pass the key as an Authorization header and get a normal 200 response immediately. Billing is monthly via flat USDC subscription.

curl -X POST https://api.safebrowz.com/v1/detect \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -d '{"url":"https://example.com"}'

Email [email protected] with your expected volume (req/min + monthly total) to provision a key. Typical tier is 10,000 to 100,000 requests per minute, rate-limited per-key so your throughput is isolated from every other enterprise customer.

// REFERENCE

Endpoints

POST/v1/detect

Return a scam/phishing verdict for a URL. Requires x402 payment.

Request body

{"url": "https://example.com"}

Response (200)

FieldTypeDescription
verdictstringsafe / caution / danger
trust_scoreinteger0-100 trustworthiness score (100 = safe, 0 = scam)
brandstring / nullImpersonated brand if detected (e.g., "Ledger", "Trezor", "PayPal")
confidencenumber0.0-1.0. How sure we are of the verdict. Not "fake percentage."
reasonstringHuman-readable explanation
threat_typesstring[]Top-level categories: wallet_drainer, seed_phrase_phishing, brand_impersonation, crypto_scam, crypto_airdrop_scam, credential_phishing, account_phishing, delivery_scam, government_impersonation, invoice_scam, tech_support_scam, fake_captcha, pastejacking
signalsobjectAll 22 boolean flags (includes domain_mismatch, no_contact_info, fake_urgency, too_good_prices, suspicious_payment, etc.)
detailsobjectmatched_brand, official_domain, domain_matches_brand, target_country, page_language, tld, domain_age_days, matched_patterns
GET/v1/status

Health check. No payment required.

{"status": "ok", "version": "1.0.0", "chain": "solana"}
// ERROR CODES

Errors

StatusErrorMeaning
400missing_urlRequest body did not include a url field.
400invalid_urlURL was malformed, too long, or pointed at a private IP.
402payment_requiredNo payment headers. Body contains instructions for all supported chains.
402payment_invalidPayment headers were supplied but verification failed. Get a fresh nonce and retry. Response body re-issues the full payment instructions.
409nonce_already_usedThis nonce was already claimed. Retry with a fresh 402 nonce.
429rate_limitedToo many requests per minute. Back off and retry.
// FAQ

Common questions

Is there an API to detect scam or phishing URLs?

Yes. Send any URL to POST /v1/detect and SafeBrowz returns a verdict (safe, caution, or danger), the impersonated brand if any, a trust score, and 22 threat signals, usually in 50 to 150 ms. It uses the same 3-layer engine (local rules, threat APIs, and AI page analysis) as the SafeBrowz browser extension.

How much does the scam detection API cost?

Two options: pay-per-call at 0.01 USD per request via x402 (USDC on Solana or Base, no signup), or a flat monthly plan from 20 USD per month with a Bearer key and an included request allowance, billed monthly. High-volume integrators get custom rate limits on request.

Can I use it in a link shortener, marketplace, or chat app?

Yes. Call the API before you shorten a link, publish a listing, or deliver a message, then block on danger, hold on caution, and allow on safe. The flat monthly Bearer plan is built for exactly this kind of steady, server-side, high-volume use.

Why x402 instead of API keys?

For the public endpoint, x402 means no signup forms, no rate tiers, no billing emails, no support tickets. You pay 0.01 USDC and get a result. No relationship required. For wallet apps and AI platforms serving millions of users behind a proxy, we issue enterprise Bearer keys on request (see the enterprise pricing FAQ below).

What's the latency?

Most verdicts return in 50-150 ms. URL-pattern matches are similar. Fresh URLs that need a page fetch and AI scan typically take 2-4 seconds end-to-end. Payment verification against Solana or Base RPC adds ~300-500 ms on top of that, regardless of scan depth.

How does this compare to the browser extension?

Every signal the extension detects - credential_phishing, pastejacking, fake_captcha (ClickFix), wallet_drainer, no_contact_info, fake_urgency, and 17 more - is returned by this API. The underlying detection pipeline is the same: URL rules, then a full AI page scan when a fresh assessment is needed. You get the same trust_score, the same brand identification, the same signals object.

Can I request a refund?

No refunds. The payment is non-reversible by design (onchain settlement). If the API returns a 5xx server error, retry with the same nonce - we do not consume nonces on server-side failures.

Do you offer enterprise / flat-rate pricing?

Yes. We provision long-lived Bearer API keys for wallet apps, AI agent platforms, and other high-volume integrators where per-call onchain signing is impractical. Each key gets its own rate limit (typically 10,000 to 100,000 requests per minute) and is billed monthly in USDC. Pass it as Authorization: Bearer sk_live_... and the x402 flow is skipped. Email [email protected] with expected volume and we will onboard you.

What data do you see?

Only the URL you send. We do not log page contents, cookies, headers, or user identifiers. The onchain transaction signature (Solana or Base) is stored for replay protection and revenue accounting.

Ready to integrate?

No forms to fill. Point any Solana or EVM wallet at api.safebrowz.com/v1/detect and start scanning.