Base URL
https://api.crytify.com
身份验证
每个 API 请求都使用 Bearer token 格式携带你的 API key。无论 HTTP 方法是什么都是同样的方式——/v1/ip 和 /v1/trust 是 POST,而 /v1/usage 和 /v1/me 是 GET。
curl -X POST "https://api.crytify.com/v1/trust" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer cry_live_xxxxxxxxxxxx" \
-d '{ ... }'
IP Lookup
当你只需要网络情报时使用 /v1/ip。消耗 1 点额度,不返回信任决策。
curl -X POST "https://api.crytify.com/v1/ip" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer cry_live_xxxxxxxxxxxx" \
-d '{
"ip": "8.8.8.8"
}'
{
"request_id": "req_123",
"ip": "8.8.8.8",
"network": {
"country": "US",
"network_type": "business"
},
"credits": {
"charged": 1,
"remaining_today": 999
}
}
BIN Lookup
免费 · 无需 API key
根据任意支付卡的前 6–8 位数字(BIN/IIN)查询卡组织、类型、发卡行和国家。无需身份验证——限制为每个 IP 每分钟 10 次请求。
curl "https://api.crytify.com/api/bin/453201"
{
"bin": "453201",
"scheme": "Visa",
"type": "Debit",
"brand": "Visa Classic",
"prepaid": false,
"bank": {
"name": "Jyske Bank",
"city": "Silkeborg",
"phone": "+4589893300"
},
"country": {
"name": "Denmark",
"code": "DK",
"emoji": "🇩🇰",
"currency": "DKK"
}
}
| 字段 | 说明 |
| bin |
你查询的 BIN(6–8 位数字)。 |
| scheme |
卡组织:Visa、Mastercard、Amex 等。 |
| type |
Credit、Debit 或 Prepaid。 |
| brand |
子品牌(例如 Visa Classic、Mastercard Gold)。 |
| prepaid |
如果是预付卡则为 true。 |
| bank.name |
发卡银行名称。 |
| country.code |
ISO 3166-1 alpha-2 国家代码。 |
| country.currency |
ISO 4217 货币代码。 |
如果数据库中没有该 BIN 则返回 HTTP 404。超出速率限制时返回 HTTP 429——请退避后于 60 秒后重试。
Trust Decision
在渲染受保护内容之前使用 /v1/trust。传入 IP、方法、路径以及脱敏后的浏览器请求头。也可以选择性地附带来自 JavaScript SDK 的 fingerprint 对象,以提升请求一致性分析的准确度。 ↳ JavaScript SDK
curl -X POST "https://api.crytify.com/v1/trust" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer cry_live_xxxxxxxxxxxx" \
-d '{
"ip": "203.0.113.5",
"mode": "hard",
"method": "POST",
"path": "/login",
"url": "https://app.example.com/login",
"challenge_return_url": "https://app.example.com/login",
"headers": {
"user-agent": "Mozilla/5.0 ...",
"accept": "text/html,application/xhtml+xml",
"accept-language": "en-US,en;q=0.9",
"sec-ch-ua-platform": "\"Windows\""
},
"fingerprint": {
"client_context": "generated by the Crytify JavaScript SDK"
}
}'
{
"request_id": "req_456",
"decision": "CHALLENGE",
"mode": "hard",
"trust_score": 42,
"risk_score": 61,
"reasons": [
"identity_risk"
],
"challenge": {
"type": "hosted",
"url": "https://crytify.com/challenge/abc123",
"expires_in": 600,
"token_param": "crytify_challenge_token"
},
"network": {
"country": "US",
"network_type": "unknown"
},
"credits": {
"charged": 8,
"remaining_today": 992
}
}
托管验证流程
当决策为 CHALLENGE 时,将访客重定向到 challenge.url。验证完成后,Crytify 会带着 crytify_challenge_token 跳转回 challenge_return_url。请在下一次 /v1/trust 调用中将该值作为 challenge_token 发送。
测试模式
在探索接入流程时,可以在请求体中加入 "test": true。真实的决策引擎仍然照常运行——返回与生产环境相同的 ALLOW/CHALLENGE/BLOCK——但该请求的任何内容都不会写入 Crytify 的自学习数据(IP、ASN 或指纹信誉)。额度依然照常扣除,并且该请求会在你的控制台中被标记为测试请求。
永远不要在真实访客流量中发送 test: true——这仅用于你自己的探索性/接入测试。如果不加这个参数反复测试(例如反复用 curl、同一个 IP 多次调用),会像其他任何流量一样,真实地在你自己的 IP 上累积自学习信誉记录。
想直接在自己的网站上用 crytify_gate() 测试?把它放进选项数组里就行,不用自己去改请求体:
crytify_gate('cry_live_xxxxxxxxxxxx', ['test' => true]);
Usage
GET · 免费——不消耗额度
查询已认证 key 所属账户的每日剩余额度和套餐限制。适合在你自己的控制台中展示用量,或在额度耗尽前提前预警。
curl "https://api.crytify.com/v1/usage" \
-H "Authorization: Bearer cry_live_xxxxxxxxxxxx"
{
"user_id": 7,
"plan": "free",
"credits": {
"daily_limit": 1000,
"daily_used": 42,
"daily_remaining": 958,
"unlimited": false,
"balance": 0,
"reset_at": "2026-07-04T00:00:00Z"
}
}
Me
GET · 免费——不消耗额度
返回当前使用的 API key 的元数据以及账户当前的套餐信息。适合在不打开控制台的情况下确认哪个 key/模式正在生效。
curl "https://api.crytify.com/v1/me" \
-H "Authorization: Bearer cry_live_xxxxxxxxxxxx"
{
"api_key": {
"id": 22,
"name": "Default Key",
"prefix": "cry_live_b6ba5ef81c422782",
"default_mode": "medium",
"can_override_mode": false,
"status": "active",
"created_at": "2026-07-03 01:05:42"
},
"account": {
"id": 7,
"plan": "free"
}
}
模式与额度
| 模式 |
额度 |
适用场景 |
| easy | 2 | 低摩擦的内容页面。 |
| medium | 4 | 表单、账户页面及通用保护的默认模式。 |
| hard | 8 | 登录、注册、结账、后台管理与 API 保护。 |
错误代码
| 代码 | HTTP | 含义 |
| invalid_json |
400 |
请求体不是合法的 JSON。 |
| missing_required_field |
400 |
缺少必需字段,例如 ip。 |
| invalid_ip |
400 |
提交的 IP 地址无效。 |
| invalid_api_key |
401 |
API key 缺失或无效。 |
| insufficient_credits |
402 |
钱包额度不足。 |
| rate_limited |
429 |
请求过于频繁。 |
| internal_error |
500 |
内部错误。已扣除的额度会被退还。 |
执行示例
你的应用决定如何处理返回的决策。一个典型的预渲染拦截大致如下:
if ($decision === 'BLOCK') {
http_response_code(403);
exit('Blocked');
}
if ($decision === 'CHALLENGE') {
header('Location: ' . $result['challenge']['url']);
exit;
}
if (!empty($_GET['crytify_challenge_token'])) {
// Send this token in the next /v1/trust call as challenge_token.
}
renderProtectedPage();
页面保护
SDK · 双层拦截
Crytify SDK 让你可以在页面内容被渲染或可见之前就把它从机器人面前隐藏起来。这里有两个互补的层级——搭配使用可获得最大覆盖面。
1
服务端拦截(PHP)
在渲染任何内容之前,在你的 PHP 代码中评估访客 IP 与请求头。可拦截所有机器人——包括不执行 JavaScript 的那些(curl、Python requests、Scrapy、wget)。
2
客户端拦截(JS)
<head> 中的脚本会立即隐藏页面,收集一致性元数据,只有在信任检查通过后才显示内容。
Browser → Your server → Crytify /v1/trust
↓ PHP 拦截(渲染前)
Browser → crytify-protect.js → Your endpoint → Crytify /v1/trust
↓ JS 拦截(可见前)
只有你的入口页面需要完整检查。 如果访客在已经运行过 crytify_gate() 的页面之后,稳定地到达其他受保护页面(结账、账户),可以改用 crytify_require_pass()——一种免费、仅基于 cookie 的检查,没有 API 调用也不消耗额度。 查看工作原理 →
JavaScript SDK
crytify-protect.js 是一个即插即用的脚本,加载后立即隐藏你的页面,收集浏览器指纹,并发送给你的后端。只有在后端确认访客被允许后,内容才会显示。
1. 嵌入到 <head> 中——放在其他任何脚本之前
<head>
<!-- Must be the first script in <head> -->
<script src="/crytify-protect.js"
data-endpoint="/api/crytify-check"
data-block-url="/blocked"
data-timeout="5000">
</script>
</head>
选项
| 属性 |
是否必需 |
说明 |
| data-endpoint |
是 |
你后端信任检查接口的 URL。JS 会把指纹 POST 到这里。 |
| data-block-url |
否 |
访客被拦截时重定向到这里。默认显示内联的拦截提示。 |
| data-timeout |
否 |
如果你的接口没有响应,多少毫秒后自动 fail open(照常显示内容)。默认:5000。 |
| data-debug |
否 |
设为 "true" 可在浏览器控制台打印决策日志。 |
2. 创建后端接口(data-endpoint)
JS 会向你的接口 POST { "fingerprint": { ... } }。你的接口调用 Crytify,并返回 { "allow": true } 或 { "allow": false }。
<?php
// /api/crytify-check.php — the endpoint crytify-protect.js calls
require 'CrytifyClient.php';
header('Content-Type: application/json');
$body = json_decode(file_get_contents('php://input'), true);
$fingerprint = $body['fingerprint'] ?? null;
$crytify = new CrytifyClient('cry_live_xxxxxxxxxxxx');
$result = $crytify->trust(
CrytifyClient::resolveIp(),
getallheaders(),
['fingerprint' => $fingerprint]
);
echo json_encode(['allow' => $result->isAllow(), 'reason' => $result->reason()]);
Fail-open 安全机制: 如果你的接口无法访问,或响应时间超过 data-timeout 设置的毫秒数,脚本会自动显示页面内容。这可以防止 Crytify 服务中断影响到你真实用户的正常访问。
PHP SDK
CrytifyClient.php 是一个无依赖的独立 PHP 类,可以放在项目的任意位置。把它当作 middleware 使用,在发送任何一个字节的 HTML 之前就拦截页面渲染。
下载
# Copy the file into your project
cp crytify-sdk/CrytifyClient.php your-project/lib/CrytifyClient.php
基本用法——服务端拦截
把这段代码放在你想保护的 PHP 页面最顶部,在任何输出之前。
<?php
require 'CrytifyClient.php';
$crytify = new CrytifyClient('cry_live_xxxxxxxxxxxx', mode: 'medium');
$result = $crytify->trust(
CrytifyClient::resolveIp(), // resolves CF-Connecting-IP / X-Forwarded-For automatically
getallheaders(),
['path' => $_SERVER['REQUEST_URI'], 'method' => $_SERVER['REQUEST_METHOD']]
);
if ($result->isBlock()) {
http_response_code(403);
include 'blocked.html';
exit;
}
if ($result->isChallenge()) {
header('Location: ' . $result->challengeUrl());
exit;
}
// Visitor passed — render your page normally
CrytifyResult 方法
| 方法 | 返回值 | 说明 |
| isAllow() |
bool |
访客通过时为 true。 |
| isChallenge() |
bool |
建议进行额外验证时为 true。 |
| isBlock() |
bool |
访客应被拒绝时为 true。 |
| challengeUrl() |
?string |
决策为 CHALLENGE 时的 Crytify 托管验证页 URL。 |
| decision() |
string |
原始决策字符串:ALLOW、CHALLENGE 或 BLOCK。 |
| trustScore() |
int |
0–100。数值越高代表越可信。 |
| riskScore() |
int |
0–100。数值越高代表越可疑。 |
| reason() |
string |
决策对应的可读原因字符串。 |
| isFailOpen() |
bool |
因网络错误触发自动 fail-open 时为 true。 |
CodeIgniter 4 过滤器
对于 CI4 项目,可以使用提供的过滤器类以声明式方式保护路由。
// app/Config/Filters.php
public array $aliases = [
'crytify' => \App\Filters\CrytifyGateFilter::class,
];
// app/Config/Routes.php — protect individual routes
$routes->get('checkout', 'OrderController::checkout', ['filter' => 'crytify']);
// Or protect an entire group
$routes->group('members', ['filter' => 'crytify'], function ($routes) {
$routes->get('dashboard', 'MemberController::dashboard');
$routes->get('profile', 'MemberController::profile');
});
浏览器指纹
在 /v1/trust 中传入 fingerprint 对象,可以补充仅凭服务器请求头无法获得的客户端一致性上下文。具体信号的处理逻辑是私有的,公开响应只会展示宽泛的原因分类。
公开分类
| 信号 | 含义 | 置信度 |
| fingerprint_risk |
客户端一致性上下文对该决策有所贡献。 |
公开分类 |
| automation_risk |
与自动化相关的上下文对该决策有所贡献。 |
公开分类 |
| identity_risk |
会话或身份一致性上下文对该决策有所贡献。 |
公开分类 |
用 JS 辅助工具采集指纹
crytify-fingerprint.js 会采集所有信号并返回一个普通对象。如果你想自己采集指纹并发送给服务器,而不使用自动隐藏页面的行为,可以单独使用它。
<script src="/crytify-fingerprint.js"></script>
<script>
crytifyFingerprint().then(function (fp) {
// fp is a plain JS object — send it to your server
fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: document.getElementById('email').value,
password: document.getElementById('password').value,
fingerprint: fp, // <-- include fingerprint in your form submission
}),
});
});
</script>
之后你的服务器只需把 fingerprint 直接放进 /v1/trust 的请求体中传递即可。不需要新的 Crytify 接口。