Docs
API Documentation
Quick Start
The NetKrypton Cloud API tells you whether a domain is listed in the NetKrypton threat database (phishing, malware, fraud and other dangerous sites). It is a single JSON endpoint:
- Create an account at cloud.netkrypton.com and
subscribe to a plan. Your API key (
nk_…) appears in the panel right after payment. - Send your first request:
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://cloud.netkrypton.com/api.php?domain=example.com"
All responses are JSON (Content-Type: application/json) and CORS is enabled, so
the API can also be called directly from a browser.
Authentication
Every request must include your API key. Three ways are supported:
| Method | Example |
|---|---|
| Authorization header (recommended) | Authorization: Bearer nk_… |
| X-API-Key header | X-API-Key: nk_… |
| Query parameter | ?key=nk_… |
Check a Domain
| Parameter | Required | Description |
|---|---|---|
domain | yes | Domain to check. A full URL is accepted too, see normalization. |
key | no* | API key, if not sent in a header. |
{
"domain": "bad-example.com",
"threat": true,
"threat_type": "phishing",
"approved_at": "2026-06-01T14:32:00Z"
}
{
"domain": "example.com",
"threat": false
}
Each call uses 1 request from your monthly quota.
Check Multiple Domains
Check up to 100 domains in a single call. It is much faster than sending separate requests, because the whole list is answered in one round-trip.
Option A — GET with a comma-separated list
Option B — POST with a JSON body (recommended for long lists)
Content-Type: application/json
{
"domains": ["a.com", "b.com", "c.com"]
}
{
"count": 3,
"threats": 1,
"results": [
{ "domain": "a.com", "threat": true, "threat_type": "phishing", "approved_at": "2026-06-01T14:32:00Z" },
{ "domain": "b.com", "threat": false },
{ "domain": "not a domain", "error": "Invalid domain format." }
]
}
| Field | Description |
|---|---|
count | Number of entries in results. |
threats | How many of the checked domains are flagged. |
results | One object per unique domain, in the same format as
the single-domain response. Invalid entries are listed at the end with an
error field. |
How batch requests are counted
- Every unique, valid domain uses 1 request from your quota.
- Duplicates are merged (
example.comandwww.example.comcount once). Invalid entries are free. - If the batch would exceed your remaining quota, the whole call is rejected with
429and nothing is charged. - More than 100 entries returns
400; split larger lists into chunks of 100.
Response Format
| Field | Type | Description |
|---|---|---|
domain | string | The normalized domain that was checked. |
threat | boolean | true if the domain is in the NetKrypton threat database. |
threat_type | string | Category of the threat, e.g. phishing, malware, scam. Present only when threat is true. |
approved_at | string | When the entry was verified and added (ISO 8601, UTC). Present only when threat is true. |
Treat unknown threat_type values as dangerous; new categories may be added over
time.
Domain Normalization
You can pass a bare domain or a full URL. Before the lookup the API:
- removes
http:///https://, the path, query string and port; - lowercases the domain and strips a leading
www.; - converts internationalized domains (e.g.
zażółć.pl) to punycode.
So https://WWW.Example.com:443/login?x=1 is checked as
example.com. The normalized value is returned in the domain field.
Errors
Errors use standard HTTP status codes and a JSON body with an error message:
{ "error": "Invalid or inactive API key." }
| Status | Meaning |
|---|---|
200 | Success. |
400 | Missing or invalid domain, invalid JSON body, or more than 100 domains in a batch. |
401 | API key missing, invalid, or the subscription is inactive. |
405 | HTTP method not allowed (use GET or POST). |
429 | Monthly quota exceeded. The body includes quota, used and resets (and requested for batches). |
5xx | Temporary server error. Retry later. |
{
"error": "Monthly quota exceeded.",
"plan": "developer",
"quota": 5000,
"used": 5000,
"resets": "2026-11-01"
}
Plans, Quotas & Rate-Limit Headers
| Plan | Requests / month | Data freshness |
|---|---|---|
| Developer | 5,000 | results cached up to 24 h |
| Pro | 50,000 | results cached up to 12 h |
| Business | 500,000 | near real-time (cache up to 60 s) |
Quotas reset on the 1st day of each month. Every successful response includes these headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Your monthly quota. |
X-RateLimit-Remaining | Requests left this month (after the current call). |
X-RateLimit-Reset | Unix timestamp of the next quota reset. |
X-Plan | Plan of the API key used. |
See pricing for plan details.
Code Examples
Single domain
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://cloud.netkrypton.com/api.php?domain=example.com"<?php
$ctx = stream_context_create(['http' => [
'header' => 'Authorization: Bearer YOUR_API_KEY',
'timeout' => 3,
'ignore_errors' => true,
]]);
$json = @file_get_contents(
'https://cloud.netkrypton.com/api.php?domain=' . urlencode('example.com'),
false,
$ctx
);
$data = $json ? json_decode($json, true) : null;
if (!empty($data['threat'])) {
echo "Dangerous: {$data['threat_type']}";
}const res = await fetch(
"https://cloud.netkrypton.com/api.php?domain=" + encodeURIComponent("example.com"),
{ headers: { Authorization: "Bearer YOUR_API_KEY" } }
);
const data = await res.json();
if (data.threat) {
console.log("Dangerous:", data.threat_type);
}import requests
r = requests.get(
"https://cloud.netkrypton.com/api.php",
params={"domain": "example.com"},
headers={"Authorization": "Bearer YOUR_API_KEY"},
timeout=3,
)
data = r.json()
if data.get("threat"):
print("Dangerous:", data["threat_type"])Multiple domains
curl -X POST "https://cloud.netkrypton.com/api.php" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"domains": ["example.com", "example.org", "example.net"]}'<?php
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => "Authorization: Bearer YOUR_API_KEY\r\nContent-Type: application/json",
'content' => json_encode(['domains' => ['example.com', 'example.org']]),
'timeout' => 5,
'ignore_errors' => true,
]]);
$json = @file_get_contents('https://cloud.netkrypton.com/api.php', false, $ctx);
$data = $json ? json_decode($json, true) : null;
foreach ($data['results'] ?? [] as $r) {
if (!empty($r['threat'])) {
echo "{$r['domain']}: {$r['threat_type']}\n";
}
}const res = await fetch("https://cloud.netkrypton.com/api.php", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ domains: ["example.com", "example.org"] }),
});
const { results } = await res.json();
const flagged = results.filter((r) => r.threat);
console.log(flagged);import requests
domains = ["example.com", "example.org", "example.net"]
flagged = []
# Split long lists into chunks of 100 (the per-call maximum)
for i in range(0, len(domains), 100):
r = requests.post(
"https://cloud.netkrypton.com/api.php",
json={"domains": domains[i:i + 100]},
headers={"Authorization": "Bearer YOUR_API_KEY"},
timeout=5,
)
flagged += [x for x in r.json()["results"] if x.get("threat")]
print(flagged)Best Practices
- Use batches when checking many domains (e.g. all links in a message or a page). One call with 100 domains is far faster than 100 calls.
- Set a short timeout (2–5 s) and decide what happens on failure. For most user-facing apps it is best to fail open (allow the action, log the error) rather than block users when the API is unreachable.
- Cache results on your side for a while. A domain checked a minute ago rarely needs to be checked again, and it saves your quota.
- Watch
X-RateLimit-Remainingand alert yourself before the quota runs out. - Handle
429gracefully: retrying will not help until the quota resets on the 1st of the month or you upgrade your plan.
Self-Hosted Database
Need unlimited queries or offline lookups? The free Self-Hosted edition lets you download the domain list and check it on your own infrastructure, with no API key and no quota. The public list is refreshed every 48 hours; download it again to stay up to date.
Download: list.netkrypton.com