“What Content Security Policy does a CAPTCHA widget need?”
What Content Security Policy does the CaptchaKit widget need?
Short answer
Allow the CaptchaKit script and its game iframe. The widget script loads from captchakit.com/widget.js and the game runs in an iframe served from captchakit.com, so add that host to script-src and frame-src. The widget makes no requests from your page, so connect-src needs no change. Open your browser console after loading the form: any remaining violation names the directive to fix.
Steps
- 1
Add captchakit.com to script-src
The page loads `widget.js` from that host.
- 2
Add captchakit.com to frame-src
The game renders in an iframe from `/widget-frame/`.
- 3
Reload with the console open
Any violation message names the directive and the blocked URL.
What the widget loads
The embed has two parts. A script tag loads `https://captchakit.com/widget.js`. That script finds each `data-gamecaptcha` div, then inserts an iframe whose source is `https://captchakit.com/widget-frame/<game>`, with your site key in the query string. The script takes its host from its own `src`, so the iframe always comes from the same host as the script.
The script does not make network requests of its own. The game inside the iframe fetches its challenge and pass token from captchakit.com, and those requests are made by the iframe document under its own policy. A parent page's `connect-src` does not govern them. The token reaches your page by a `postMessage` from the iframe, which a Content Security Policy does not restrict.
Policy snippet
Add the CaptchaKit host to two directives. Keep your existing entries, and replace `'self'` with whatever your policy already uses.
Content-Security-Policy:
script-src 'self' https://captchakit.com;
frame-src 'self' https://captchakit.com;If you do not set frame-src
MDN documents that when `frame-src` is absent, the browser falls back to `child-src`, and `child-src` falls back to `default-src`. If your policy only sets `default-src 'self'`, the iframe is blocked until you add the CaptchaKit host to one of those three directives. Putting it in `frame-src` is the narrowest choice.
If your policy uses nonces, give the CaptchaKit script tag the same nonce as your other scripts. The inline snippet you write to read the `gamecaptcha:pass` event is your own code and needs a nonce or hash like any inline script.
Test in the console
Load the page with the form, open the browser developer tools and watch the console. A blocked script reads as a `script-src` violation naming the URL. A blocked game reads as a `frame-src` or `child-src` violation. Fix the named directive and reload. If the widget area stays blank with no message, check that your ad or content blocker is not blocking `captchakit.com`.
The server-side check, `POST /api/verify`, runs from your backend, so a browser Content Security Policy does not apply to it.
Questions
Which directives does the widget need?
script-src for the widget.js script and frame-src for the game iframe, both for captchakit.com.
Does it need connect-src?
Not on your page. The requests to captchakit.com are made inside the iframe, under the iframe's own policy.
Does it need unsafe-inline or unsafe-eval?
The widget script is an external file, so it does not need unsafe-inline for itself. Your own inline listener code follows your usual nonce or hash rules.
Why is the widget area blank?
A Content Security Policy block, a content blocker or a wrong site key. Check the console for a violation message first.
Which directive blocks the game iframe?
frame-src, or child-src and default-src if frame-src is not set, per MDN.
Can the iframe be embedded on any site?
Yes. The widget frame is served with frame-ancestors set to any origin so that customer sites can embed it.
Sources
- MDN: Content-Security-Policy frame-src (checked 2026-10-18)
- CaptchaKit widget.js (checked 2026-10-18)
- CaptchaKit documentation (checked 2026-10-18)
Related
Protect your forms with a game
Every arcade CAPTCHA we make. Sign up, grab your embed code, protect your forms today.
Get started →Pay what you want. Start free.