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.
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.
Agent Skill (markdown)
Complete skill definition with triggers, payment flow, signal interpretation, code examples. Ready to paste into any agent framework.
Download skill.mdOpenAPI 3.1 Spec
Machine-readable endpoint schema. Use with ChatGPT Actions, Postman, Insomnia, or any SDK generator.
View openapi.jsonLLM-friendly Docs
Full plain-text reference optimized for AI crawlers and agent context windows. Includes citation guidance.
View api-llms.txtPlugin manifest at /.well-known/ai-plugin.json
One price. No tiers.
Per request
Pay in USDC on Solana or Base mainnet. No subscription, no commitment. Cache hits are still billed at the same rate - keeps integration simple and covers infrastructure.
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.
Brands tracked
Covers wallets (MetaMask, Phantom, Ledger, Trezor), exchanges (Binance, Coinbase, OKX), payment services (PayPal, Venmo, Stripe), and major global consumer brands.
Run the full x402 flow in your browser
Connect any wallet, paste a URL, click test. Pay 0.001 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.
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; alternatives include Solana SOL and Base USDC.
{
"status": 402,
"error": "payment_required",
"payment": {
"amount": "0.001",
"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": "SOL", "amount": "0.00001", "chain": "solana", "nonce_binding": "memo", "memo_format": "safebrowz:..." },
{ "token": "USDC", "amount": "0.001", "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.001 USDC (or 0.00001 SOL) 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.001 \
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", 1000n ], // 0.001 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."
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.001", 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 info@safebrowz.com 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.
Endpoints
Return a scam/phishing verdict for a URL. Requires x402 payment.
Request body
{"url": "https://example.com"}
Response (200)
| Field | Type | Description |
|---|---|---|
verdict | string | safe / caution / danger |
trust_score | integer | 0-100 trustworthiness score (100 = safe, 0 = scam) |
brand | string / null | Impersonated brand if detected (e.g., "Ledger", "Trezor", "PayPal") |
confidence | number | 0.0-1.0. How sure we are of the verdict. Not "fake percentage." |
reason | string | Human-readable explanation |
threat_types | string[] | 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 |
signals | object | All 22 boolean flags (includes domain_mismatch, no_contact_info, fake_urgency, too_good_prices, suspicious_payment, etc.) |
details | object | matched_brand, official_domain, domain_matches_brand, target_country, page_language, tld, domain_age_days, matched_patterns |
Health check. No payment required.
{"status": "ok", "version": "1.0.0", "chain": "solana"}
Errors
| Status | Error | Meaning |
|---|---|---|
| 400 | missing_url | Request body did not include a url field. |
| 400 | invalid_url | URL was malformed, too long, or pointed at a private IP. |
| 402 | payment_required | No payment headers. Body contains instructions for all supported chains. |
| 402 | payment_invalid | Payment headers were supplied but verification failed. Get a fresh nonce and retry. Response body re-issues the full payment instructions. |
| 409 | nonce_already_used | This nonce was already claimed. Retry with a fresh 402 nonce. |
| 429 | rate_limited | Too many requests per minute. Back off and retry. |
Common questions
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.001 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?
Cached verdicts return in 50-150 ms. URL-pattern matches are similar. Fresh URLs that need a page fetch + 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 shared: cache, URL rules, then a full AI page scan on cache miss. 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 info@safebrowz.com 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.