CSP header parser API
Reads a Content-Security-Policy value as CSP Level 3 does: every policy and directive, 'unsafe-inline' and 'unsafe-eval', wildcard and scheme-only sources for scripts and plugins, missing default-src, object-src and base-uri, repeated, unknown and removed directives, and report-only mode. Nothing is fetched.
POST https://api.lookproof.dev/v1/http/csp-parse
Updated 2026-10-09
Examples use the Base (eip155:8453) network.
Input
A JSON body with content-type: application/json.
| Name | Type | Required | Limits | Description |
|---|---|---|---|---|
header | string | Yes | 1–8192 characters | A Content-Security-Policy value, at most 8192 characters; Content-Security-Policy: or ...-Report-Only: in front is optional. |
Example request
curl -i -X POST https://api.lookproof.dev/v1/http/csp-parse \
-H 'content-type: application/json' \
-d '{"header": "Content-Security-Policy: default-src '"'"'self'"'"'; script-src '"'"'self'"'"' '"'"'unsafe-inline'"'"' https://cdn.example.com; object-src '"'"'none'"'"'; base-uri '"'"'self'"'"'"}'import asyncio
import os
from eth_account import Account
from x402 import x402Client
from x402.http.clients import x402HttpxClient
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact import register_exact_evm_client
async def main() -> None:
signer = EthAccountSigner(Account.from_key(os.environ["EVM_PRIVATE_KEY"]))
client = register_exact_evm_client(x402Client(), signer, networks="eip155:8453")
async with x402HttpxClient(client) as http:
response = await http.post('https://api.lookproof.dev/v1/http/csp-parse', json={'header': "Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.example.com; object-src 'none'; base-uri 'self'"})
response.raise_for_status()
print(response.json())
asyncio.run(main())
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.EVM_PRIVATE_KEY);
const fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, {
schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }],
});
const response = await fetchWithPayment("https://api.lookproof.dev/v1/http/csp-parse", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({"header": "Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.example.com; object-src 'none'; base-uri 'self'"}),
});
console.log(await response.json());
curl: unpaid request — returns 402 with the price (PAYMENT-REQUIRED). The Python and JavaScript clients pay it and send the request again. Only ordinary wallets (EOA) can pay; smart-contract wallets get a 402 without charge. See payments.
Example response
{
"checked_at": "2026-10-24T12:00:00Z",
"data": {
"header_name": "content-security-policy",
"notes": [
"Only the pasted text is read; whether a site sends this header is not checked."
],
"policies": [
{
"directives": [
{
"name": "default-src",
"sources": [
"'self'"
]
},
{
"name": "script-src",
"sources": [
"'self'",
"'unsafe-inline'",
"https://cdn.example.com"
]
},
{
"name": "object-src",
"sources": [
"'none'"
]
},
{
"name": "base-uri",
"sources": [
"'self'"
]
}
]
}
],
"report_only": false
},
"endpoint": "http.csp_parse",
"findings": [
{
"code": "CSP_UNSAFE_INLINE",
"evidence": {
"count": 1,
"items": [
{
"directive": "script-src",
"policy": "1",
"source": "'unsafe-inline'"
}
]
},
"explanation": "The script-src directive (or default-src, when there is no script-src) allows 'unsafe-inline' without a nonce or hash, or allows 'unsafe-eval'. Injected inline scripts can then run, which removes most of the protection the policy gives against cross-site scripting.",
"message": "The Content Security Policy allows inline or eval'd scripts.",
"recommendation": "Move inline scripts to files or allow them with nonces or hashes, and drop 'unsafe-eval' once no code needs eval().",
"severity": "info"
}
],
"meta": {
"cache_hit": false,
"duration_ms": 42,
"fresh_until": "2026-10-24T12:05:00Z",
"observed_at": "2026-10-24T12:00:00Z",
"resolver": null,
"source": "offline"
},
"request_id": "req_aaaaaaaaaaaaaaaaaaaaaaaaaa",
"schema_version": "1.0",
"status": "info"
}
Response fields
| Field | Meaning |
|---|---|
request_id | Unique id of this request. Quote it when you contact support. |
endpoint | The endpoint id, for example mail.spf. |
schema_version | Version of the response format, currently 1.0. |
checked_at | When the check ran (ISO 8601, UTC). |
status | ok, info, warning or error from the worst finding, or unknown when the check was incomplete. unknown is not an error in the domain. |
data | The check's own data. Its fields are listed below. |
findings | What was found: code, severity, message, explanation and evidence. |
meta | Duration, cache use, resolver and how long the result stays fresh. |
Fields in data
| Field | Type |
|---|---|
header_name | string or null |
report_only | boolean |
policies | array of CspPolicy |
notes | array of string |
Status codes
| Status | Code | Meaning | Do you pay? |
|---|---|---|---|
| 200 | — | The result is delivered, also when it has negative findings. | Yes: charged once per payment; redelivery of the same payment is free |
| 402 | — | Payment is required, or the attached payment was refused. The body states the price. | No |
| 400 | bad_request | The request is malformed. | No |
| 409 | payment_in_progress, payment_bound_to_other_request | This payment is already being processed, or it is bound to a different request. No new payment is taken. | No |
| 413 | payload_too_large | The body is larger than 64 KB. | No |
| 422 | invalid_input | The input failed validation on a request that carries a payment; nothing is charged. Without a payment, invalid input gets a 402 whose error field names the problem. | No |
| 429 | rate_limited | Too many requests from this IP address or payer. | No |
| 502 | check_failed | The check could not be completed. | No |
| 503 | busy, unavailable, payments_unavailable | The service is busy or temporarily unavailable. | No |
| 504 | deadline_exceeded | The check ran out of time. | No |
Errors use the common error body. See errors.
Findings this endpoint can return
Content Security Policy (10)
- Info
CSP_DEPRECATED_DIRECTIVEThe policy uses a directive that has been removed from CSP. - Warning
CSP_DUPLICATE_DIRECTIVEA directive appears twice in one policy, and browsers ignore the second one. - Error
CSP_EMPTY_POLICYThe pasted Content-Security-Policy has no directives. - Info
CSP_NO_BASE_URIThe policy does not restrict the base element (base-uri). - Warning
CSP_NO_DEFAULT_SRCThe policy has no default-src directive. - Warning
CSP_NO_OBJECT_SRCPlugin content (object and embed elements) is not restricted. - Info
CSP_REPORT_ONLYThis is a report-only policy: browsers report violations but block nothing. - Info
CSP_UNKNOWN_DIRECTIVEThe policy has a directive that CSP Level 3 does not define. - Info
CSP_UNSAFE_INLINEThe Content Security Policy allows inline or eval'd scripts. - Warning
CSP_WILDCARD_SOURCEScripts or plugins may load from any host or from inline data.