Scannd Documentation
Scannd is automated website vulnerability scanning. Point it at your domain, run a scan at the depth your plan unlocks, and pull the findings from the dashboard, the REST API, or any MCP-compatible AI assistant.
Overview & Getting Started
Scannd runs Nuclei against the domains registered on your account and saves the findings to a report. How many classes of check run depends on your plan's scan depth (see Scan Tiers & Depth). You can trigger scans and read results from the web dashboard, the REST API, or an AI assistant over MCP.
Get started in four steps
- 1.Sign in. Log in to the dashboard with Auth0 (see Authentication).
- 2.Add your targets. Register the domains you want scanned on the Targets page. How many you can hold at once depends on your plan: Free 1, Solo 3, Startup 10, Agency 30, Partner unlimited. The first target you add becomes your primary and is mirrored onto your account's registered domain; later ones do not change it.
- 3.Run a scan. Use the Run Scan bar on the Targets page to scan the targets you tick, the dashboard's scan button for your registered domain, or trigger one programmatically (see Running a Scan).
- 4.Read the report. Findings are stored, emailed to you, and available through the API (see Reports & Vulnerabilities).
Multi-target scanning is live. The Targets page in the sidebar adds and removes targets, and its Run Scan bar enqueues one scan per target you select. Two things to know: the dashboard's own scan button is the older single-scan path and runs against your account's registered domain, and adding targets is metered per calendar month on top of the concurrent limit (Free 2, Solo 6, Startup 20, Agency and Partner unlimited), so rotating domains through a small plan's slots is not unlimited.
Authentication
Scannd has two ways in: Auth0 for the web console, and API keys for programmatic and MCP access.
Console login (Auth0)
The dashboard authenticates with Auth0 (OpenID Connect). Signing in issues a short-lived access token that the console sends as an Authorization: Bearer <token> header on its requests. The public Auth0 configuration the front end initializes with is served from GET /api/config. Your Auth0 identity (auth0_user_id) is the key everything else in your account hangs off.
API keys
API keys authenticate the REST API and the MCP server. To get one:
- 1.Sign in to the dashboard.
- 2.Open the API keys panel and click Generate (optionally give the key a label).
- 3.Copy the key. It starts with
sk_and is shown only once. Store it somewhere safe.
Send the key in an X-API-Key header on every request. Keys are stored as a SHA-256 hash server-side (Scannd can't recover the original), so if you lose one, revoke it from the dashboard and generate a new one. Revoking takes effect immediately.
Running a Scan
A scan runs against a domain registered on your account (you can't point a scan at an arbitrary URL). You can start one three ways:
- Dashboard. The scan button in the console triggers a scan of your account's registered domain at your plan's depth. The Targets page has its own Run Scan bar, which enqueues one scan per target you tick.
- REST API.
POST /api/mcp/v1/scanwith your API key (see API Reference). - MCP. The
trigger_scantool, so an AI assistant can start a scan for you (see MCP Integration).
Scan lifecycle
A triggered scan moves through these statuses. The dashboard scan button and the MCP trigger_scan tool allow only one scan at a time per account; starting a second while one is in progress returns a conflict. The Targets page fan-out is the exception: it enqueues one scan per target you selected, and those queue against the platform's shared scan capacity rather than all starting at once.
Scans take a few minutes. Poll status with get_scan_status (MCP) or GET /api/mcp/v1/scan/{scan_id}/status. When a scan completes, the report is saved and emailed to you.
You can also opt in to weekly scheduled scans per target on the Targets page; enrolled targets are scanned automatically once a week.
Scan Tiers & Depth
Your plan maps to a scan depth, which controls how many classes of check Nuclei runs. Depths are a strict superset ladder: each deeper level runs everything the level below it does, plus more.
| Plan | Price | Scan depth |
|---|---|---|
| Free | $0/mo | free |
| Solo | $39/mo | standard |
| Startup | $149/mo | professional |
| Agency | $399/mo | professional |
| Partner | Contact sales | professional |
What each depth runs
free
2,500+ checks availableA surface-hygiene scan: TLS/SSL and DNS checks, subdomain takeover, exposed files and services, technology fingerprinting, default logins, and leaked tokens. It does not run CVE matching or active web-vulnerability tests.
standard
10,000+ checks availableEverything in free, plus configuration and infrastructure hardening (misconfigurations, exposed panels, WordPress/CMS, cloud config), the full CVE database, and active web-vulnerability classes: XSS, SQLi, LFI, SSRF, XXE, SSTI, IDOR, auth-bypass, API, GraphQL, and deserialization. It does not run the professional-only discovery recon corpus.
professional
12,000+ checks availableEverything in standard, plus the professional-only discovery premium recon corpus (the “whale” tag that is the single biggest coverage jump on the ladder) and the aggressive/offensive block: remote code execution (RCE), unauthenticated-access, and intrusive checks. This is the deepest coverage Scannd runs.
The discovery tag is a premium recon corpus held to professional depth only; it is not part of free or standard. This is the “whale” that makes a Startup scan (professional) meaningfully deeper than a Solo scan (standard): both run the CVE database and the active web-vulnerability classes, but only professional adds the discovery corpus (and the aggressive/offensive block).
The check counts above are the number of templates available at each depth — the size of the library a scan at that depth draws on, not a count of requests sent to your site. They were measured on 25 July 2026 against the production template image, using the same tag filter Scannd runs for that depth, and they are floors rounded down: templates are pulled from ProjectDiscovery's latest release on a 24-hour loop, so the exact totals move a little every day.
As a share of the professional ceiling (same 25 July 2026 measurement), free is ≈ 25% and standard ≈ 89%; the professional-only discovery recon corpus is the bulk of that gap. professional is the deepest depth Scannd runs, but it is not the whole library — it is ≈ 94% of the templates loaded in production.
An intermediate basic depth (config/infra hardening, between free and standard) exists internally but is not sold as a plan; its checks are all included in standard.
Reports & Vulnerabilities
Every completed scan produces a report, stored against your account and emailed to you. You can also read reports programmatically, over the REST API or through MCP tools.
Retrieving results
list_reports: recent reports (metadata only):id,filename,created_at.get_report: a specific report by id, or the latest, with its full findings list.get_vulnerabilities: findings from a report, optionally filtered by severity.get_domain_summary: a roll-up of your tier, total scans, last scan time, and vulnerability counts by severity.
Reading a finding
Each finding carries the fields below. Severity is one of critical, high, medium, low, or info.
{
"name": "string", // the check that matched
"severity": "critical | high | medium | low | info",
"url": "string", // where it was found
"description": "string",
"template_id": "string" // the Nuclei template
}
The domain summary rolls these up into counts: { "critical", "high", "medium", "low", "info" }.
MCP Integration
Connect Scannd to Claude, Cursor, or any MCP-compatible AI assistant to trigger scans, pull findings, and check your domain's posture from a conversation. The scannd-mcp server exposes eight tools backed by the REST API.
Setup
Generate an API key, then add this to your MCP client's config (e.g. claude_desktop_config.json):
{
"mcpServers": {
"scannd": {
"command": "npx",
"args": ["scannd-mcp"],
"env": {
"SCANND_API_KEY": "sk_your_key_here"
}
}
}
}
How it authenticates
The server reads SCANND_API_KEY from its env block and sends it in an X-API-Key header on every request to Scannd. If the variable is missing, the server won't start.
Tool reference
trigger_scan
Rate-limitedQueues a security scan for one of the targets on your account (not an arbitrary domain). Pass target_id, or domain as a convenience alias for it; omit both and it resolves to the single target the key can reach, or returns a 400 listing your targets when the key can reach several. Returns a scan_id to poll with get_scan_status.
{ "workflow"?: "free" | "standard" | "professional", "target_id"?: number, "domain"?: "string" }
{ "scan_id": "string", "status": "queued", "message": "string" }
workflow selects the scan depth; it defaults to your subscription's depth. Requesting a depth above your plan is rejected.
get_scan_status
Read-onlyPolls the status of a previously triggered scan.
{ "scan_id": "string" }
{ "scan_id": "string", "status": "queued" | "running" | "completed" | "failed" }
list_reports
Read-onlyLists past scan reports for your account (metadata only, no findings).
{ "limit"?: number } // default 10, clamped to 1–50
{ "reports": [{ "id": number, "filename": "string", "created_at": "string | null" }] }
get_report
Read-onlyReturns the full content of a specific report, or the latest report if report_id is omitted.
{ "report_id"?: "string" } // omit for latest
{ "report_id": number, "created_at": "string | null", "findings": [...] }
get_vulnerabilities
Read-onlyReturns findings from a report, optionally filtered by severity. Useful for "show me just critical and high findings."
{ "report_id"?: "string", "severity"?: "critical" | "high" | "medium" | "low" | "info" }
{ "report_id": number, "findings": [{ "name", "severity", "url", "description", "template_id" }] }
get_domain_summary
Read-onlyReturns a high-level summary of your domain: subscription tier, scan history, and vulnerability counts from the most recent scan.
none
{ "domain", "tier", "total_scans", "last_scan_at", "vuln_counts": { "critical", "high", "medium", "low", "info" } }
list_templates
Read-onlyLists the scan depths available to trigger_scan. tag_count is the number of tag categories in that depth, not the raw Nuclei template count.
none
{ "workflows": [{ "name", "description", "tag_count" }] }
list_targets
Read-onlyLists the targets your API key can act on. Use it to discover a target_id to pass to the other tools when your account has more than one target.
none
{ "targets": [{ "id", "domain", "label" }] }
API Reference
Base URL https://api.scannd.com. All responses are JSON.
MCP REST API (v1)
These endpoints authenticate with an X-API-Key header and back the eight MCP tools. (get_report maps to two routes (/reports/latest and /reports/{id}), so nine routes serve eight tools.)
| Method | Path | Params | Returns |
|---|---|---|---|
| POST | /api/mcp/v1/scan | body: workflow? (free|standard|professional) | scan_id, status, message |
| GET | /api/mcp/v1/scan/{scan_id}/status | path: scan_id (uuid) | scan_id, status |
| GET | /api/mcp/v1/reports | query: limit? (1-50, default 10) | reports[] |
| GET | /api/mcp/v1/reports/latest | - | report_id, created_at, findings[] |
| GET | /api/mcp/v1/reports/{report_id} | path: report_id (int) | report_id, created_at, findings[] |
| GET | /api/mcp/v1/reports/{report_id}/vulnerabilities | path: report_id (int or "latest"); query: severity? | report_id, findings[] |
| GET | /api/mcp/v1/domain/summary | - | domain, tier, total_scans, last_scan_at, vuln_counts |
| GET | /api/mcp/v1/templates | - | workflows[] |
| GET | /api/mcp/v1/targets | - | targets[] |
API key management
These endpoints manage your keys and are used by the authenticated dashboard (Auth0 session, scoped to your auth0_user_id). The raw key is returned only on creation.
| Method | Path | Params | Returns |
|---|---|---|---|
| POST | /api/mcp/keys | body: auth0_user_id, label? | id, api_key (shown once), label, created_at |
| GET | /api/mcp/keys | query: auth0_user_id | keys[] (id, label, created_at, last_used_at) |
| DELETE | /api/mcp/keys/{key_id} | path: key_id; query: auth0_user_id | success, message |
| GET | /api/mcp/usage | query: auth0_user_id | scan_count, limit (2 or "unlimited"), tier |
The dashboard also uses a set of authenticated console endpoints (scan trigger, domain, reports, subscription, and weekly-scan preference). Those are console-internal and not part of the public developer API documented here.
Rate Limits
Scan limits apply to the scans you trigger via MCP / the REST API. Only the Free tier is capped; every paid plan runs unlimited scans.
| Plan | Price | Scans via MCP / month |
|---|---|---|
| Free | $0/mo | 2 |
| Solo | $39/mo | Unlimited |
| Startup | $149/mo | Unlimited |
| Agency | $399/mo | Unlimited |
| Partner | Contact sales | Unlimited |
Read-only tools (report and vulnerability lookups) aren't rate-limited. Only trigger_scan counts against your monthly total, and the count is aggregated across all of an account's API keys.
Independently of the monthly cap, only one scan runs at a time per account on the dashboard and MCP triggers: starting a second while one is in progress returns a conflict until the first finishes.
There is also a per-target cooldown. Scans of a target are limited to one per hour by default; your other targets are unaffected, so adding targets adds throughput. This applies to every plan, paid ones included — "unlimited scans" means no monthly cap, not unlimited back-to-back scans of the same host.
Troubleshooting & FAQ
sk_ and is shown only once, so copy it right away. See Authentication.
SCANND_API_KEY is set in your client config's env block; the server exits immediately if it's missing.
X-API-Key header starting with sk_. Generate a fresh key from your dashboard and update your client config; keys are only shown once at creation.
trigger_scan returns a limit error until your usage resets next month, or you upgrade to any paid plan (Solo, Startup, Agency, or Partner) for unlimited scans. If you instead get a "scan already in progress" error, wait for your current scan to finish; only one runs at a time.
target_id (or domain) to trigger_scan. Scans stay confined to targets on your own account — you still can't point one at an arbitrary URL. Note that the dashboard's scan button is the older single-scan path and runs against your account's registered domain, and that scans of any one target are limited to one per hour by default; your other targets are unaffected.
get_scan_status with the scan_id returned by trigger_scan, or just ask your assistant to check again in a bit; it can call the tool for you. A completed scan is also emailed to you.