---
title: "Scan a website's Content-Security-Policy"
method: POST
path: "/csp/scan"
tags: ["web"]
---

# Scan a website's Content-Security-Policy

`POST /csp/scan`

## Request

- Base URL: `https://intodns.ai/api`
- URL: `https://intodns.ai/api/csp/scan`
- Auth: none required

Crawl up to 20 same-origin pages (45s total budget), analyze the current Content-Security-Policy (enforce header, Report-Only header, or meta tag), detect weaknesses such as unsafe-inline, wildcard sources, and missing object-src/base-uri/frame-ancestors, inventory every external resource origin per directive, and synthesize a ready-to-deploy starter policy (enforce + Report-Only variants). Expensive endpoint: limited to 3 scans per 10 minutes per IP; results are cached per origin for 10 minutes so repeat scans are instant. A scan typically takes 30-45 seconds.

## Request body

- CspScanRequest
  - `url` string, required: Site to scan. A bare hostname is treated as https://
  - `strict` boolean: Synthesize a stricter policy

## Response `200`

CSP scan completed

- CspScanResult
  - `url` string: Normalized start URL of the crawl
  - `origin` string
  - `pagesCrawled` integer: Number of same-origin pages successfully crawled (max 20)
  - `pagesFailed` integer
  - `truncated` boolean: True when more pages were discovered than the crawl budget allowed
  - `currentCsp` object: The policy currently deployed, if any
    - `source` 'header' | 'report-only' | 'meta', nullable: Where the policy was found; null when the site has no CSP
    - `policy` string, nullable
  - `findings` object[]: Weaknesses detected in the current policy (or the absence of one)
    - `id` string
    - `severity` 'critical' | 'high' | 'medium' | 'info'
    - `title` string
    - `description` string
    - `directive` string
  - `inventory` object[]: Observed resource origins grouped by CSP directive ('self' first, externals sorted)
    - `directive` string
    - `origins` string[]
  - `inlineScripts` integer: Total inline script blocks across crawled pages
  - `inlineStyles` integer
  - `eventHandlerAttrs` integer: Total inline event-handler attributes (onclick, onload, ...)
  - `synthesis` object: Generated starter policy built from observed resources
    - `policyString` string: Ready-to-deploy Content-Security-Policy value
    - `reportOnlyString` string: Content-Security-Policy-Report-Only value for safe rollout
    - `notes` string[]

## Other responses

- `400`: Invalid body or URL that cannot be scanned (IP literals, localhost, non-https, internal hostnames)
- `429`: Rate limit exceeded — 3 scans per 10 minutes per IP; retry after the Retry-After header
- `502`: Inconclusive — no page could be crawled, so no findings or policy are reported

---

[API](https://skmtc.dev/intodns/apis/intodns-ai-api.md) · [All operations](https://skmtc.dev/intodns/apis/intodns-ai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/intodns/apis/intodns-ai-api/revisions/c6c196b2fb4c?raw)
